diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..36bd2d5c --- /dev/null +++ b/.coveragerc @@ -0,0 +1,25 @@ +# .coveragerc to control coverage.py +# following the example at http://nedbatchelder.com/code/coverage/config.html +[run] +branch = True +include = helpdesk/* +omit = + *helpdesk/south_migrations/* + *helpdesk/migrations/* + +[report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + + # Don't complain if non-runnable code isn't run: + if 0: + if __name__ == .__main__.: + if __name__==.__main__.: + +ignore_errors = True \ No newline at end of file diff --git a/.gitignore b/.gitignore index ee1c29b2..7f84b87d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ django_helpdesk.egg-info docs/html/* docs/doctrees/* +.coverage .project .pydevproject diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000..6d986bd6 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,378 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS,migrations,south_migrations + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins=pylint_django + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Allow optimization of some AST trees. This will activate a peephole AST +# optimizer, which will apply various small optimizations. For instance, it can +# be used to obtain the result of joining multiple strings with the addition +# operator. Joining a lot of strings can lead to a maximum recursion error in +# Pylint and this flag can prevent that. It has one side effect, the resulting +# AST will be different than the one from reality. +optimize-ast=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=import-star-module-level,old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=120 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). This supports can work +# with qualified names. +ignored-classes= + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[ELIF] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/.travis.yml b/.travis.yml index 1f5b9ac0..96106b6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,18 +6,23 @@ python: - "3.5" env: - - DJANGO=1.7.11 - - DJANGO=1.8.7 - - DJANGO=1.9 - -matrix: - exclude: - - python: "3.5" # django 1.7 does not support python 3.5 - env: DJANGO=1.7.11 + - DJANGO=1.8.15 + - DJANGO=1.9.10 + - DJANGO=1.10.2 install: - pip install argparse + - pip install coverage + - pip install codecov + - pip install pep8 - pip install -q Django==$DJANGO - pip install -q -r requirements.txt -script: python quicktest.py helpdesk \ No newline at end of file +before_script: + - "pep8 --exclude=migrations,south_migrations --ignore=E501 helpdesk" + +script: + - coverage run --source='.' quicktest.py helpdesk + +after_success: + - codecov diff --git a/AUTHORS b/AUTHORS index bedd41ea..ebb11164 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,13 +1,24 @@ -django-helpdesk was originally written by Ross Poulton. Since publishing the -code a number of people have made some fantastic improvements and provided -bug fixes and updates as the Django codebase has moved on and caused small -portions of this application to break. +django-helpdesk was originally written by Ross Poulton. After nearly nine +years under his guidance, the project graduated to its own eponymous +organization, and is currently maintained by: -To these people, and any more, my sincere thanks: +Alex Seeholzer (@flinz) +Garret Wassermann (@gwasser) +Jonathan Barratt (@reduxionist) +Since publishing the code a number of people have made some fantastic +improvements and provided bug fixes and updates as the Django codebase +has moved on and caused small portions of this application to break. + +To these people, and many more, our sincere thanks: + +Alex Barcelo Andreas Kotowicz Chris Etcp +Daryl Egarr David Clymer Loe Spee Maxim Litnitskiy Nikolay Panov +Stefano Brentegani +Tony Zhu diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 48a93cf3..00000000 --- a/CHANGELOG +++ /dev/null @@ -1,64 +0,0 @@ -2009-09-09 r138 Issue #104 Add a CHANGELOG file - -2009-09-09 r139 Issue #102 Add Ticket CC's -Add rudimentary CC: functionality on tickets, controlled by staff users. CC's -can be e-mail addresses or users, who will receive copies of all emails sent -to the Submitter. This is a work in progress. - -2009-09-09 r140 Issue #13 Add Tags to tickets -Patch courtesy of david@zettazebra.com, adds the ability to add tags to -tickets if django-tagging is installed and in use. If django-tagging isn't -being used, no change is visible to the user. - -2009-10-13 r141 Issue #118 Incorrect locale handling on email templates -Patch courtesy of hgeerts. Corrects the handling of locale on email -templaets, defaulting to English if no locale is provided. - -2009-10-13 r142 Issue #117 Incorrect I18N usage in a few spots -Patch thanks to hgeerts. - -2009-10-13 r143 Issue #113 - Clicking Queue names on the Dashboard was showing -all tickets; now only shows open tickets. Thanks to Andreas Kotowicz for the -sugestion. - -2009-12-16 r144 Issue #122 - Infinite loop when most recent ticket was -opened in December. Thanks to Chris Vigelius for the report. - -2009-12-16 r145 issue #123 - Google Chart doesn't show when there is a large -volume of data in the system. This patch restricts the chart to 1000px wide. - -2009-12-16 r146 Issue #121 Formatting fix for email subjects. Thanks, -Andreas Kotowicz. - -2009-12-16 r147 Issue #119 Update Russian translation, thanks to Alex Yakovlev - -2009-12-23 r148 Issue #125 Errors occurring when running reports with no data - -2010-01-20 r149 Issue #126 Reports didn't work with transalations. - -2010-01-20 r150 Issue #127 Add german transalation, courtesy of openinformation.org - -2009-01-20 r151 Issue #128 If queue name has a dash in it, email imported failed. Thanks to enix.org for the patch. - -2010-01-21 r152 Fix indentation error caused by issue #126. - -2010-01-26 r153 Fix issue #129 - can not 'unassign' tickets. Thanks to -lukeman for the patch. - -2010-01-26 r154 Fix bug in the code from Issue #102 where TicketCC's couldn't -be deleted. Thanks again to lukeman. - -2010-01-31 r155 Fix bug caused by issue #129 - ticket followup titles being -set incorrectly. Thanks to Lukeman for the fix. - -2010-07-16 r157 Fix issues #141, #142 - IMAP infinite loops and ticket -pagination issues. Thanks to Walter Doekes for the patches. - -2010-07-16 r158 New CSRF functionality for Django 1.1+. Thanks to -'litchfield4' for the patch. - -2010-09-04 r159 Error when updating multiple tickets. Issue #135. - -2010-09-04 r160 Fix translation blocks in deletion templates. Some translation strings will need to be updated. Thanks to william88 for the bug report. - -2010-09-04 r161 Fix jQuery filename in public templates. Thanks to bruno.braga for the fix. diff --git a/MANIFEST.in b/MANIFEST.in index d277e6cb..f7e76ad8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,6 @@ -include README -include UPGRADE +include README.rst +include AUTHORS include LICENSE* -include CHANGELOG include requirements.txt recursive-include helpdesk/static/helpdesk * diff --git a/README.rst b/README.rst index b57499ea..32d6027c 100644 --- a/README.rst +++ b/README.rst @@ -1,13 +1,16 @@ django-helpdesk - A Django powered ticket tracker for small businesses. ======================================================================= -.. image:: https://travis-ci.org/rossp/django-helpdesk.png?branch=master - :target: https://travis-ci.org/rossp/django-helpdesk +.. image:: https://travis-ci.org/django-helpdesk/django-helpdesk.png?branch=master + :target: https://travis-ci.org/django-helpdesk/django-helpdesk + +.. image:: https://codecov.io/gh/django-helpdesk/django-helpdesk/branch/master/graph/badge.svg + :target: https://codecov.io/gh/django-helpdesk/django-helpdesk Copyright 2009- Ross Poulton and contributors. All Rights Reserved. See LICENSE for details. -django-helpdesk was formerly known as Jutda Helpdesk, named after the -company who originally created it. As of January 2011 the name has been +django-helpdesk was formerly known as Jutda Helpdesk, named after the +company which originally created it. As of January 2011 the name has been changed to reflect what it really is: a Django-powered ticket tracker with contributors reaching far beyond Jutda. @@ -18,15 +21,15 @@ You can see a demo installation at http://django-helpdesk-demo.herokuapp.com/ Licensing --------- -See the file 'LICENSE' for licensing terms. Note that django-helpdesk is -distributed with 3rd party products which have their own licenses. See +See the file 'LICENSE' for licensing terms. Note that django-helpdesk is +distributed with 3rd party products which have their own licenses. See LICENSE.3RDPARTY for license terms for included packages. Dependencies (pre-flight checklist) ----------------------------------- 1. Python 2.7 or 3.4+ (3.4+ support is new, please let us know how it goes) -2. Django (1.7 or newer, preferably 1.9 - Django 1.7 is not supported if you are using Python 3.5) +2. Django (1.8+, preferably 1.10) 3. An existing WORKING Django project with database etc. If you cannot log into the Admin, you won't get this product working. 4. `pip install django-bootstrap-form` and add `bootstrapform` to `settings.INSTALLED_APPS` @@ -45,12 +48,12 @@ When you try to do a keyword search using sqlite, a message will be displayed to alert you to this shortcoming. There is no way around it, sorry. **NOTE REGARDING MySQL:** -If you use MySQL, with most default configurations you will receive an error -when creating the database tables as we populate a number of default templates -in languages other than English. +If you use MySQL, with most default configurations you will receive an error +when creating the database tables as we populate a number of default templates +in languages other than English. -You must create the database the holds the django-helpdesk tables using the -UTF-8 collation; see the MySQL manual for more information: +You must create the database the holds the django-helpdesk tables using the +UTF-8 collation; see the MySQL manual for more information: http://dev.mysql.com/doc/refman/5.1/en/charset-database.html If you do NOT do this step, and you only want to use English-language templates, @@ -61,20 +64,20 @@ Fresh Django Installations -------------------------- If you're on a brand new Django installation, make sure you do a ``migrate`` -**before** adding ``helpdesk`` to your ``INSTALLED_APPS``. This will avoid +**before** adding ``helpdesk`` to your ``INSTALLED_APPS``. This will avoid errors with trying to create User settings. Upgrading from previous versions -------------------------------- If you are upgrading from a previous version of django-helpdesk that used -migrations, get an up to date version of the code base (eg by using +migrations, get an up to date version of the code base (eg by using `git pull` or `pip install --upgrade django-helpdesk`) then migrate the database:: python manage.py migrate helpdesk --db-dry-run # DB untouched - python manage.py migrate helpdesk + python manage.py migrate helpdesk -Lastly, restart your web server software (eg Apache) or FastCGI instance, to +Lastly, restart your web server software (eg Apache) or FastCGI instance, to ensure the latest changes are in use. If you are using django-helpdesk pre-migrations (ie pre-2011) then you're @@ -94,11 +97,8 @@ Contributing If you want to help translate django-helpdesk into languages other than English, we encourage you to make use of our Transifex project. -https://www.transifex.com/rossp/django-helpdesk/ +https://www.transifex.com/django-helpdesk/django-helpdesk/ Feel free to request access to contribute your translations. Pull requests for all other changes are welcome. We're currently trying to add test cases wherever possible, so please continue to include tests with pull requests. - -.. image:: https://secure.travis-ci.org/rossp/django-helpdesk.png?branch=master - :target: https://travis-ci.org/rossp/django-helpdesk diff --git a/build_project.sh b/build_project.sh index bda3c5e8..d80575b8 100755 --- a/build_project.sh +++ b/build_project.sh @@ -5,7 +5,7 @@ WORKDIR=/tmp/django-helpdesk-build.$$ mkdir $WORKDIR pushd $WORKDIR -git clone git://github.com/rossp/django-helpdesk.git +git clone git://github.com/django-helpdesk/django-helpdesk.git cd django-helpdesk /usr/bin/python setup.py sdist upload diff --git a/docs/api.rst b/docs/api.rst deleted file mode 100644 index f7f6404b..00000000 --- a/docs/api.rst +++ /dev/null @@ -1,8 +0,0 @@ -Ticket API -========== - -*Warning*: The django-helpdesk API is deprecated, and no longer maintained. See https://github.com/rossp/django-helpdesk/issues/198 for more details. - -The API will be removed in January 2016 - you should instead build an integration with eg django-rest-framework. - -For details on the current API including usage instructions and command syntax, see the file ``templates/helpdesk/api_help.html``, or visit http://helpdesk/api/help/. diff --git a/docs/contributing.rst b/docs/contributing.rst index 63c874eb..e4cff162 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -32,7 +32,7 @@ Wherever possible please break git commits up into small chunks that are specifi Commit messages should also explain *what*, precisely, has been changed. -If you have any questions, please contact the project co-ordinator, Ross Poulton, at ross@rossp.org. +If you have any questions, please start a discussion on the GitHub issue tracker at https://github.com/django-helpdesk/django-helpdesk/issues Tests ----- diff --git a/docs/index.rst b/docs/index.rst index 34a62228..483d5d84 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,6 @@ Contents settings spam custom_fields - api contributing @@ -49,7 +48,7 @@ Customers (who are not 'staff' users in Django) can: 3. Review open and closed requests they submitted Staff Capabilities -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~ If a user is a staff member, they get general helpdesk access, including: diff --git a/docs/install.rst b/docs/install.rst index 7c7a7c57..ab02a73d 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -15,7 +15,7 @@ Try using ``pip install django-helpdesk``. Go and have a beer to celebrate Pytho GIT Checkout (Cutting Edge) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you're planning on editing the code or just want to get whatever is the latest and greatest, you can clone the official Git repository with ``git clone git://github.com/rossp/django-helpdesk.git`` +If you're planning on editing the code or just want to get whatever is the latest and greatest, you can clone the official Git repository with ``git clone git://github.com/django-helpdesk/django-helpdesk.git`` Copy the ``helpdesk`` folder into your ``PYTHONPATH``. @@ -49,10 +49,13 @@ Adding To Your Django Project Note that you can change 'helpdesk/' to anything you like, such as 'support/' or 'help/'. If you want django-helpdesk to be available at the root of your site (for example at http://support.mysite.tld/) then the line will be as follows:: - url(r'', include('helpdesk.urls')), + url(r'', include('helpdesk.urls', namespace='helpdesk')), This line will have to come *after* any other lines in your urls.py such as those used by the Django admin. + Note that the `helpdesk` namespace is no longer required for Django 1.9 and you can use a different namespace. + However, it is recommended to use the default namespace name for clarity. + 3. Create the required database tables. Migrate using Django migrations:: diff --git a/docs/settings.rst b/docs/settings.rst index 81ce992f..c60e3936 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -1,7 +1,7 @@ Settings ======== -First, django-helpdesk needs ``django.core.context_processors.request`` activated, so in your ``settings.py`` add:: +First, django-helpdesk needs ``django.core.context_processors.request`` activated, so you must add it to the ``settings.py``. For Django 1.7, add:: from django.conf import global_settings TEMPLATE_CONTEXT_PROCESSORS = ( @@ -9,6 +9,25 @@ First, django-helpdesk needs ``django.core.context_processors.request`` activat ('django.core.context_processors.request',) ) +For Django 1.8 and onwards, the settings are located in the ``TEMPLATES``, and the ``request`` module has moved. Add the following instead:: + + TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + ... + 'OPTIONS': { + ... + 'context_processors': ( + # Default ones first + ... + # The one django-helpdesk requires: + "django.template.context_processors.request", + ), + }, + }, + ] + + The following settings can be changed in your ``settings.py`` file to help change the way django-helpdesk operates. There are quite a few settings available to toggle functionality within django-helpdesk. HELPDESK_DEFAULT_SETTINGS @@ -23,7 +42,6 @@ If you want to override the default settings for your users, create ``HELPDESK_D 'email_on_ticket_assign': True, 'email_on_ticket_change': True, 'login_view_ticketlist': True, - 'email_on_ticket_apichange': True, 'tickets_per_page': 25 } @@ -68,6 +86,10 @@ These changes are visible throughout django-helpdesk **Default:** ``HELPDESK_EMAIL_SUBJECT_TEMPLATE = "{{ ticket.ticket }} {{ ticket.title|safe }} %(subject)s"`` +- **HELPDESK_EMAIL_FALLBACK_LOCALE** Fallback locale for templated emails when queue locale not found + + **Default:** ``HELPDESK_EMAIL_FALLBACK_LOCALE= "en"`` + Options shown on public pages ----------------------------- diff --git a/helpdesk/admin.py b/helpdesk/admin.py index 5529f2b6..3ff8c857 100644 --- a/helpdesk/admin.py +++ b/helpdesk/admin.py @@ -5,10 +5,14 @@ from helpdesk.models import EscalationExclusion, EmailTemplate, KBItem from helpdesk.models import TicketChange, Attachment, IgnoreEmail from helpdesk.models import CustomField + +@admin.register(Queue) class QueueAdmin(admin.ModelAdmin): list_display = ('title', 'slug', 'email_address', 'locale') prepopulated_fields = {"slug": ("title",)} + +@admin.register(Ticket) class TicketAdmin(admin.ModelAdmin): list_display = ('title', 'status', 'assigned_to', 'queue', 'hidden_submitter_email',) date_hierarchy = 'created' @@ -24,34 +28,38 @@ class TicketAdmin(admin.ModelAdmin): return ticket.submitter_email hidden_submitter_email.short_description = _('Submitter E-Mail') + class TicketChangeInline(admin.StackedInline): model = TicketChange + class AttachmentInline(admin.StackedInline): model = Attachment + +@admin.register(FollowUp) class FollowUpAdmin(admin.ModelAdmin): inlines = [TicketChangeInline, AttachmentInline] + +@admin.register(KBItem) class KBItemAdmin(admin.ModelAdmin): list_display = ('category', 'title', 'last_updated',) list_display_links = ('title',) + +@admin.register(CustomField) class CustomFieldAdmin(admin.ModelAdmin): list_display = ('name', 'label', 'data_type') + +@admin.register(EmailTemplate) class EmailTemplateAdmin(admin.ModelAdmin): list_display = ('template_name', 'heading', 'locale') list_filter = ('locale', ) -admin.site.register(Ticket, TicketAdmin) -admin.site.register(Queue, QueueAdmin) -admin.site.register(FollowUp, FollowUpAdmin) admin.site.register(PreSetReply) admin.site.register(EscalationExclusion) -admin.site.register(EmailTemplate, EmailTemplateAdmin) admin.site.register(KBCategory) -admin.site.register(KBItem, KBItemAdmin) admin.site.register(IgnoreEmail) -admin.site.register(CustomField, CustomFieldAdmin) diff --git a/helpdesk/akismet.py b/helpdesk/akismet.py index 98ac4e1d..9a99c881 100644 --- a/helpdesk/akismet.py +++ b/helpdesk/akismet.py @@ -15,7 +15,7 @@ """ A python interface to the `Akismet `_ API. -This is a web service for blocking SPAM comments to blogs - or other online +This is a web service for blocking SPAM comments to blogs - or other online services. You will need a Wordpress API key, from `wordpress.com `_. @@ -24,7 +24,7 @@ You should pass in the keyword argument 'agent' to the name of your program, when you create an Akismet instance. This sets the ``user-agent`` to a useful value. -The default is : :: +The default is:: Python Interface by Fuzzyman | akismet.py/0.2.0 @@ -32,9 +32,9 @@ Whatever you pass in, will replace the *Python Interface by Fuzzyman* part. **0.2.0** will change with the version of this interface. Usage example:: - + from akismet import Akismet - + api = Akismet(agent='Test Script') # if apikey.txt is in place, # the key will automatically be set @@ -55,7 +55,7 @@ Usage example:: """ -import os, sys +import os from urllib import urlencode import socket @@ -70,7 +70,7 @@ __all__ = ( 'Akismet', 'AkismetError', 'APIKeyError', - ) +) __author__ = 'Michael Foord ' @@ -92,7 +92,7 @@ if urllib2 is None: req = urlfetch.fetch(url=url, payload=data, method=urlfetch.POST, headers=headers) if req.status_code == 200: return req.content - raise Exception('Could not fetch Akismet URL: %s Response code: %s' % + raise Exception('Could not fetch Akismet URL: %s Response code: %s' % (url, req.status_code)) else: def _fetch_url(url, data, headers): @@ -104,9 +104,13 @@ else: class AkismetError(Exception): """Base class for all akismet exceptions.""" + pass + class APIKeyError(AkismetError): """Invalid API key.""" + pass + class Akismet(object): """A class for working with the akismet API""" @@ -120,38 +124,35 @@ class Akismet(object): self.user_agent = user_agent % (agent, __version__) self.setAPIKey(key, blog_url) - def _getURL(self): """ Fetch the url to make requests to. - + This comprises of api key plus the baseurl. """ return 'http://%s.%s' % (self.key, self.baseurl) - - + def _safeRequest(self, url, data, headers): try: resp = _fetch_url(url, data, headers) - except Exception, e: + except Exception as e: raise AkismetError(str(e)) return resp - def setAPIKey(self, key=None, blog_url=None): """ Set the wordpress API key for all transactions. - + If you don't specify an explicit API ``key`` and ``blog_url`` it will attempt to load them from a file called ``apikey.txt`` in the current directory. - + This method is *usually* called automatically when you create a new ``Akismet`` instance. """ if key is None and isfile('apikey.txt'): the_file = [l.strip() for l in open('apikey.txt').readlines() - if l.strip() and not l.strip().startswith('#')] + if l.strip() and not l.strip().startswith('#')] try: self.key = the_file[0] self.blog_url = the_file[1] @@ -161,30 +162,29 @@ class Akismet(object): self.key = key self.blog_url = blog_url - def verify_key(self): """ This equates to the ``verify-key`` call against the akismet API. - + It returns ``True`` if the key is valid. - + The docs state that you *ought* to call this at the start of the transaction. - + It raises ``APIKeyError`` if you have not yet set an API key. - + If the connection to akismet fails, it allows the normal ``HTTPError`` or ``URLError`` to be raised. (*akismet.py* uses `urllib2 `_) """ if self.key is None: raise APIKeyError("Your have not set an API key.") - data = { 'key': self.key, 'blog': self.blog_url } + data = {'key': self.key, 'blog': self.blog_url} # this function *doesn't* use the key as part of the URL url = 'http://%sverify-key' % self.baseurl # we *don't* trap the error here # so if akismet is down it will raise an HTTPError or URLError - headers = {'User-Agent' : self.user_agent} + headers = {'User-Agent': self.user_agent} resp = self._safeRequest(url, urlencode(data), headers) if resp.lower() == 'valid': return True @@ -195,21 +195,21 @@ class Akismet(object): """ This function builds the data structure required by ``comment_check``, ``submit_spam``, and ``submit_ham``. - + It modifies the ``data`` dictionary you give it in place. (and so doesn't return anything) - + It raises an ``AkismetError`` if the user IP or user-agent can't be worked out. """ data['comment_content'] = comment - if not 'user_ip' in data: + if 'user_ip' not in data: try: val = os.environ['REMOTE_ADDR'] except KeyError: raise AkismetError("No 'user_ip' supplied") data['user_ip'] = val - if not 'user_agent' in data: + if 'user_agent' not in data: try: val = os.environ['HTTP_USER_AGENT'] except KeyError: @@ -226,55 +226,52 @@ class Akismet(object): data.setdefault('SERVER_ADMIN', os.environ.get('SERVER_ADMIN', '')) data.setdefault('SERVER_NAME', os.environ.get('SERVER_NAME', '')) data.setdefault('SERVER_PORT', os.environ.get('SERVER_PORT', '')) - data.setdefault('SERVER_SIGNATURE', os.environ.get('SERVER_SIGNATURE', - '')) - data.setdefault('SERVER_SOFTWARE', os.environ.get('SERVER_SOFTWARE', - '')) + data.setdefault('SERVER_SIGNATURE', os.environ.get('SERVER_SIGNATURE', '')) + data.setdefault('SERVER_SOFTWARE', os.environ.get('SERVER_SOFTWARE', '')) data.setdefault('HTTP_ACCEPT', os.environ.get('HTTP_ACCEPT', '')) data.setdefault('blog', self.blog_url) - def comment_check(self, comment, data=None, build_data=True, DEBUG=False): """ This is the function that checks comments. - + It returns ``True`` for spam and ``False`` for ham. - + If you set ``DEBUG=True`` then it will return the text of the response, instead of the ``True`` or ``False`` object. - + It raises ``APIKeyError`` if you have not yet set an API key. - + If the connection to Akismet fails then the ``HTTPError`` or ``URLError`` will be propogated. - + As a minimum it requires the body of the comment. This is the ``comment`` argument. - + Akismet requires some other arguments, and allows some optional ones. The more information you give it, the more likely it is to be able to make an accurate diagnosise. - + You supply these values using a mapping object (dictionary) as the ``data`` argument. - + If ``build_data`` is ``True`` (the default), then *akismet.py* will attempt to fill in as much information as possible, using default values where necessary. This is particularly useful for programs running in a {acro;CGI} environment. A lot of useful information can be supplied from evironment variables (``os.environ``). See below. - + You *only* need supply values for which you don't want defaults filled in for. All values must be strings. - + There are a few required values. If they are not supplied, and defaults can't be worked out, then an ``AkismetError`` is raised. - + If you set ``build_data=False`` and a required value is missing an ``AkismetError`` will also be raised. - + The normal values (and defaults) are as follows : :: - + 'user_ip': os.environ['REMOTE_ADDR'] (*) 'user_agent': os.environ['HTTP_USER_AGENT'] (*) 'referrer': os.environ.get('HTTP_REFERER', 'unknown') [#]_ @@ -290,16 +287,16 @@ class Akismet(object): 'SERVER_SIGNATURE': os.environ.get('SERVER_SIGNATURE', '') 'SERVER_SOFTWARE': os.environ.get('SERVER_SOFTWARE', '') 'HTTP_ACCEPT': os.environ.get('HTTP_ACCEPT', '') - + (*) Required values - + You may supply as many additional 'HTTP_*' type values as you wish. These should correspond to the http headers sent with the request. - + .. [#] Note the spelling "referrer". This is a required value by the akismet api - however, referrer information is not always supplied by the browser or server. In fact the HTTP protocol - forbids relying on referrer information for functionality in + forbids relying on referrer information for functionality in programs. .. [#] The `API docs `_ state that this value can be " *blank, comment, trackback, pingback, or a made up value* @@ -316,7 +313,7 @@ class Akismet(object): url = '%scomment-check' % self._getURL() # we *don't* trap the error here # so if akismet is down it will raise an HTTPError or URLError - headers = {'User-Agent' : self.user_agent} + headers = {'User-Agent': self.user_agent} resp = self._safeRequest(url, urlencode(data), headers) if DEBUG: return resp @@ -329,12 +326,11 @@ class Akismet(object): # NOTE: Happens when you get a 'howdy wilbur' response ! raise AkismetError('missing required argument.') - def submit_spam(self, comment, data=None, build_data=True): """ This function is used to tell akismet that a comment it marked as ham, is really spam. - + It takes all the same arguments as ``comment_check``, except for *DEBUG*. """ @@ -347,15 +343,14 @@ class Akismet(object): url = '%ssubmit-spam' % self._getURL() # we *don't* trap the error here # so if akismet is down it will raise an HTTPError or URLError - headers = {'User-Agent' : self.user_agent} + headers = {'User-Agent': self.user_agent} self._safeRequest(url, urlencode(data), headers) - def submit_ham(self, comment, data=None, build_data=True): """ This function is used to tell akismet that a comment it marked as spam, is really ham. - + It takes all the same arguments as ``comment_check``, except for *DEBUG*. """ @@ -368,5 +363,5 @@ class Akismet(object): url = '%ssubmit-ham' % self._getURL() # we *don't* trap the error here # so if akismet is down it will raise an HTTPError or URLError - headers = {'User-Agent' : self.user_agent} + headers = {'User-Agent': self.user_agent} self._safeRequest(url, urlencode(data), headers) diff --git a/helpdesk/apps.py b/helpdesk/apps.py index 8a9755a4..a573b4ca 100644 --- a/helpdesk/apps.py +++ b/helpdesk/apps.py @@ -1,6 +1,6 @@ from django.apps import AppConfig + class HelpdeskConfig(AppConfig): name = 'helpdesk' verbose_name = "Helpdesk" - diff --git a/helpdesk/forms.py b/helpdesk/forms.py index f64d9ba9..e946ebd4 100644 --- a/helpdesk/forms.py +++ b/helpdesk/forms.py @@ -6,6 +6,8 @@ django-helpdesk - A Django powered ticket tracker for small enterprise. forms.py - Definitions of newforms-based forms for creating and maintaining tickets. """ +from django.core.exceptions import ObjectDoesNotExist + try: from StringIO import StringIO except ImportError: @@ -13,27 +15,27 @@ except ImportError: from django import forms from django.forms import extras -from django.core.files.storage import default_storage from django.conf import settings -from django.utils.translation import ugettext as _ -try: - from django.contrib.auth import get_user_model - User = get_user_model() -except ImportError: - from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth import get_user_model try: from django.utils import timezone except ImportError: from datetime import datetime as timezone from helpdesk.lib import send_templated_mail, safe_template_context -from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC, CustomField, TicketCustomFieldValue, TicketDependency +from helpdesk.models import (Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC, + CustomField, TicketCustomFieldValue, TicketDependency) from helpdesk import settings as helpdesk_settings +User = get_user_model() + + class CustomFieldMixin(object): """ Mixin that provides a method to turn CustomFields into an actual field """ + def customfield_to_field(self, field, instanceargs): if field.data_type == 'varchar': fieldclass = forms.CharField @@ -52,7 +54,7 @@ class CustomFieldMixin(object): fieldclass = forms.ChoiceField choices = field.choices_as_array if field.empty_selection_list: - choices.insert(0, ('','---------' ) ) + choices.insert(0, ('', '---------')) instanceargs['choices'] = choices elif field.data_type == 'boolean': fieldclass = forms.BooleanField @@ -73,7 +75,9 @@ class CustomFieldMixin(object): self.fields['custom_%s' % field.name] = fieldclass(**instanceargs) + class EditTicketForm(CustomFieldMixin, forms.ModelForm): + class Meta: model = Ticket exclude = ('created', 'modified', 'status', 'on_hold', 'resolution', 'last_escalation', 'assigned_to') @@ -91,15 +95,14 @@ class EditTicketForm(CustomFieldMixin, forms.ModelForm): except TicketCustomFieldValue.DoesNotExist: initial_value = None instanceargs = { - 'label': field.label, - 'help_text': field.help_text, - 'required': field.required, - 'initial': initial_value, - } + 'label': field.label, + 'help_text': field.help_text, + 'required': field.required, + 'initial': initial_value, + } self.customfield_to_field(field, instanceargs) - def save(self, *args, **kwargs): for field, value in self.cleaned_data.items(): @@ -108,7 +111,7 @@ class EditTicketForm(CustomFieldMixin, forms.ModelForm): customfield = CustomField.objects.get(name=field_name) try: cfv = TicketCustomFieldValue.objects.get(ticket=self.instance, field=customfield) - except: + except ObjectDoesNotExist: cfv = TicketCustomFieldValue(ticket=self.instance, field=customfield) cfv.value = value cfv.save() @@ -117,42 +120,45 @@ class EditTicketForm(CustomFieldMixin, forms.ModelForm): class EditFollowUpForm(forms.ModelForm): - def __init__(self, *args, **kwargs): - "Filter not openned tickets here." - super(EditFollowUpForm, self).__init__(*args, **kwargs) - self.fields["ticket"].queryset = Ticket.objects.filter(status__in=(Ticket.OPEN_STATUS, Ticket.REOPENED_STATUS)) + class Meta: model = FollowUp exclude = ('date', 'user',) + def __init__(self, *args, **kwargs): + """Filter not openned tickets here.""" + super(EditFollowUpForm, self).__init__(*args, **kwargs) + self.fields["ticket"].queryset = Ticket.objects.filter(status__in=(Ticket.OPEN_STATUS, Ticket.REOPENED_STATUS)) + + class TicketForm(CustomFieldMixin, forms.Form): queue = forms.ChoiceField( widget=forms.Select(attrs={'class':'form-control'}), label=_('Queue'), required=True, choices=() - ) + ) title = forms.CharField( max_length=100, required=True, widget=forms.TextInput(attrs={'class':'form-control'}), label=_('Summary of the problem'), - ) + ) submitter_email = forms.EmailField( required=False, label=_('Submitter E-Mail Address'), widget=forms.TextInput(attrs={'class':'form-control'}), help_text=_('This e-mail address will receive copies of all public ' - 'updates to this ticket.'), - ) + 'updates to this ticket.'), + ) body = forms.CharField( widget=forms.Textarea(attrs={'class':'form-control', 'rows': 15}), label=_('Description of Issue'), required=True, - ) + ) assigned_to = forms.ChoiceField( widget=forms.Select(attrs={'class':'form-control'}), @@ -160,8 +166,8 @@ class TicketForm(CustomFieldMixin, forms.Form): required=False, label=_('Case owner'), help_text=_('If you select an owner other than yourself, they\'ll be ' - 'e-mailed details of this ticket immediately.'), - ) + 'e-mailed details of this ticket immediately.'), + ) priority = forms.ChoiceField( widget=forms.Select(attrs={'class':'form-control'}), @@ -169,28 +175,27 @@ class TicketForm(CustomFieldMixin, forms.Form): required=False, initial='3', label=_('Priority'), - help_text=_('Please select a priority carefully. If unsure, leave it ' - 'as \'3\'.'), - ) + help_text=_('Please select a priority carefully. If unsure, leave it as \'3\'.'), + ) due_date = forms.DateTimeField( widget=forms.TextInput(attrs={'class':'form-control'}), required=False, label=_('Due on'), - ) + ) def clean_due_date(self): data = self.cleaned_data['due_date'] - #TODO: add Google calendar update hook - #if not hasattr(self, 'instance') or self.instance.due_date != new_data: - # print "you changed!" + # TODO: add Google calendar update hook + # if not hasattr(self, 'instance') or self.instance.due_date != new_data: + # print "you changed!" return data attachment = forms.FileField( required=False, label=_('Attach File'), help_text=_('You can attach a file such as a document or screenshot to this ticket.'), - ) + ) def __init__(self, *args, **kwargs): """ @@ -199,14 +204,13 @@ class TicketForm(CustomFieldMixin, forms.Form): super(TicketForm, self).__init__(*args, **kwargs) for field in CustomField.objects.all(): instanceargs = { - 'label': field.label, - 'help_text': field.help_text, - 'required': field.required, - } + 'label': field.label, + 'help_text': field.help_text, + 'required': field.required, + } self.customfield_to_field(field, instanceargs) - def save(self, user): """ Writes and returns a Ticket() object @@ -214,15 +218,15 @@ class TicketForm(CustomFieldMixin, forms.Form): q = Queue.objects.get(id=int(self.cleaned_data['queue'])) - t = Ticket( title = self.cleaned_data['title'], - submitter_email = self.cleaned_data['submitter_email'], - created = timezone.now(), - status = Ticket.OPEN_STATUS, - queue = q, - description = self.cleaned_data['body'], - priority = self.cleaned_data['priority'], - due_date = self.cleaned_data['due_date'], - ) + t = Ticket(title=self.cleaned_data['title'], + submitter_email=self.cleaned_data['submitter_email'], + created=timezone.now(), + status=Ticket.OPEN_STATUS, + queue=q, + description=self.cleaned_data['body'], + priority=self.cleaned_data['priority'], + due_date=self.cleaned_data['due_date'], + ) if self.cleaned_data['assigned_to']: try: @@ -237,16 +241,16 @@ class TicketForm(CustomFieldMixin, forms.Form): field_name = field.replace('custom_', '', 1) customfield = CustomField.objects.get(name=field_name) cfv = TicketCustomFieldValue(ticket=t, - field=customfield, - value=value) + field=customfield, + value=value) cfv.save() - f = FollowUp( ticket = t, - title = _('Ticket Opened'), - date = timezone.now(), - public = True, - comment = self.cleaned_data['body'], - user = user, + f = FollowUp(ticket=t, + title=_('Ticket Opened'), + date=timezone.now(), + public=True, + comment=self.cleaned_data['body'], + user=user, ) if self.cleaned_data['assigned_to']: f.title = _('Ticket Opened & Assigned to %(name)s') % { @@ -265,7 +269,7 @@ class TicketForm(CustomFieldMixin, forms.Form): filename=filename, mime_type=mimetypes.guess_type(filename)[0] or 'application/octet-stream', size=file.size, - ) + ) a.file.save(file.name, file, save=False) a.save() @@ -290,10 +294,14 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.submitter_email) - if t.assigned_to and t.assigned_to != user and t.assigned_to.usersettings.settings.get('email_on_ticket_assign', False) and t.assigned_to.email and t.assigned_to.email not in messages_sent_to: + if t.assigned_to and \ + t.assigned_to != user and \ + t.assigned_to.usersettings.settings.get('email_on_ticket_assign', False) and \ + t.assigned_to.email and \ + t.assigned_to.email not in messages_sent_to: send_templated_mail( 'assigned_owner', context, @@ -301,7 +309,7 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.assigned_to.email) if q.new_ticket_cc and q.new_ticket_cc not in messages_sent_to: @@ -312,10 +320,12 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(q.new_ticket_cc) - if q.updated_ticket_cc and q.updated_ticket_cc != q.new_ticket_cc and q.updated_ticket_cc not in messages_sent_to: + if q.updated_ticket_cc and \ + q.updated_ticket_cc != q.new_ticket_cc and \ + q.updated_ticket_cc not in messages_sent_to: send_templated_mail( 'newticket_cc', context, @@ -323,7 +333,7 @@ class TicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) return t @@ -333,28 +343,28 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): label=_('Queue'), required=True, choices=() - ) + ) title = forms.CharField( max_length=100, required=True, widget=forms.TextInput(), label=_('Summary of your query'), - ) + ) submitter_email = forms.EmailField( required=True, label=_('Your E-Mail Address'), help_text=_('We will e-mail you when your ticket is updated.'), - ) + ) body = forms.CharField( widget=forms.Textarea(), label=_('Description of your issue'), required=True, help_text=_('Please be as descriptive as possible, including any ' - 'details we may need to address your query.'), - ) + 'details we may need to address your query.'), + ) priority = forms.ChoiceField( choices=Ticket.PRIORITY_CHOICES, @@ -362,20 +372,20 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): initial='3', label=_('Urgency'), help_text=_('Please select a priority carefully.'), - ) + ) due_date = forms.DateTimeField( widget=extras.SelectDateWidget, required=False, label=_('Due on'), - ) + ) attachment = forms.FileField( required=False, label=_('Attach File'), help_text=_('You can attach a file such as a document or screenshot to this ticket.'), max_length=1000, - ) + ) def __init__(self, *args, **kwargs): """ @@ -384,10 +394,10 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): super(PublicTicketForm, self).__init__(*args, **kwargs) for field in CustomField.objects.filter(staff_only=False): instanceargs = { - 'label': field.label, - 'help_text': field.help_text, - 'required': field.required, - } + 'label': field.label, + 'help_text': field.help_text, + 'required': field.required, + } self.customfield_to_field(field, instanceargs) @@ -399,15 +409,15 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): q = Queue.objects.get(id=int(self.cleaned_data['queue'])) t = Ticket( - title = self.cleaned_data['title'], - submitter_email = self.cleaned_data['submitter_email'], - created = timezone.now(), - status = Ticket.OPEN_STATUS, - queue = q, - description = self.cleaned_data['body'], - priority = self.cleaned_data['priority'], - due_date = self.cleaned_data['due_date'], - ) + title=self.cleaned_data['title'], + submitter_email=self.cleaned_data['submitter_email'], + created=timezone.now(), + status=Ticket.OPEN_STATUS, + queue=q, + description=self.cleaned_data['body'], + priority=self.cleaned_data['priority'], + due_date=self.cleaned_data['due_date'], + ) if q.default_owner and not t.assigned_to: t.assigned_to = q.default_owner @@ -419,17 +429,17 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): field_name = field.replace('custom_', '', 1) customfield = CustomField.objects.get(name=field_name) cfv = TicketCustomFieldValue(ticket=t, - field=customfield, - value=value) + field=customfield, + value=value) cfv.save() f = FollowUp( - ticket = t, - title = _('Ticket Opened Via Web'), - date = timezone.now(), - public = True, - comment = self.cleaned_data['body'], - ) + ticket=t, + title=_('Ticket Opened Via Web'), + date=timezone.now(), + public=True, + comment=self.cleaned_data['body'], + ) f.save() @@ -443,7 +453,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): filename=filename, mime_type=mimetypes.guess_type(filename)[0] or 'application/octet-stream', size=file.size, - ) + ) a.file.save(file.name, file, save=False) a.save() @@ -463,10 +473,13 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.submitter_email) - if t.assigned_to and t.assigned_to.usersettings.settings.get('email_on_ticket_assign', False) and t.assigned_to.email and t.assigned_to.email not in messages_sent_to: + if t.assigned_to and \ + t.assigned_to.usersettings.settings.get('email_on_ticket_assign', False) and \ + t.assigned_to.email and \ + t.assigned_to.email not in messages_sent_to: send_templated_mail( 'assigned_owner', context, @@ -474,7 +487,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(t.assigned_to.email) if q.new_ticket_cc and q.new_ticket_cc not in messages_sent_to: @@ -485,10 +498,12 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) messages_sent_to.append(q.new_ticket_cc) - if q.updated_ticket_cc and q.updated_ticket_cc != q.new_ticket_cc and q.updated_ticket_cc not in messages_sent_to: + if q.updated_ticket_cc and \ + q.updated_ticket_cc != q.new_ticket_cc and \ + q.updated_ticket_cc not in messages_sent_to: send_templated_mail( 'newticket_cc', context, @@ -496,7 +511,7 @@ class PublicTicketForm(CustomFieldMixin, forms.Form): sender=q.from_address, fail_silently=True, files=files, - ) + ) return t @@ -506,25 +521,19 @@ class UserSettingsForm(forms.Form): label=_('Show Ticket List on Login?'), help_text=_('Display the ticket list upon login? Otherwise, the dashboard is shown.'), required=False, - ) + ) email_on_ticket_change = forms.BooleanField( label=_('E-mail me on ticket change?'), help_text=_('If you\'re the ticket owner and the ticket is changed via the web by somebody else, do you want to receive an e-mail?'), required=False, - ) + ) email_on_ticket_assign = forms.BooleanField( label=_('E-mail me when assigned a ticket?'), help_text=_('If you are assigned a ticket via the web, do you want to receive an e-mail?'), required=False, - ) - - email_on_ticket_apichange = forms.BooleanField( - label=_('E-mail me when a ticket is changed via the API?'), - help_text=_('If a ticket is altered by the API, do you want to receive an e-mail?'), - required=False, - ) + ) tickets_per_page = forms.ChoiceField( label=_('Number of tickets to show per page'), @@ -537,15 +546,23 @@ class UserSettingsForm(forms.Form): label=_('Use my e-mail address when submitting tickets?'), help_text=_('When you submit a ticket, do you want to automatically use your e-mail address as the submitter address? You can type a different e-mail address when entering the ticket if needed, this option only changes the default.'), required=False, - ) + ) + class EmailIgnoreForm(forms.ModelForm): + class Meta: model = IgnoreEmail exclude = [] + class TicketCCForm(forms.ModelForm): ''' Adds either an email address or helpdesk user as a CC on a Ticket. Used for processing POST requests. ''' + + class Meta: + model = TicketCC + exclude = ('ticket',) + def __init__(self, *args, **kwargs): super(TicketCCForm, self).__init__(*args, **kwargs) if helpdesk_settings.HELPDESK_STAFF_ONLY_TICKET_CC: @@ -553,9 +570,6 @@ class TicketCCForm(forms.ModelForm): else: users = User.objects.filter(is_active=True).order_by(User.USERNAME_FIELD) self.fields['user'].queryset = users - class Meta: - model = TicketCC - exclude = ('ticket',) class TicketCCUserForm(forms.ModelForm): ''' Adds a helpdesk user as a CC on a Ticket ''' @@ -579,6 +593,7 @@ class TicketCCEmailForm(forms.ModelForm): exclude = ('ticket','user',) class TicketDependencyForm(forms.ModelForm): + class Meta: model = TicketDependency exclude = ('ticket',) diff --git a/helpdesk/lib.py b/helpdesk/lib.py index 3dfe5448..364abc1e 100644 --- a/helpdesk/lib.py +++ b/helpdesk/lib.py @@ -6,7 +6,7 @@ django-helpdesk - A Django powered ticket tracker for small enterprise. lib.py - Common functions (eg multipart e-mail) """ -chart_colours = ('80C65A', '990066', 'FF9900', '3399CC', 'BBCCED', '3399CC', 'FFCC33') +import logging try: from base64 import urlsafe_b64encode as b64encode @@ -17,13 +17,20 @@ try: except ImportError: from base64 import decodestring as b64decode -import logging -logger = logging.getLogger('helpdesk') - from django.utils.encoding import smart_str from django.db.models import Q +from django.utils.safestring import mark_safe -def send_templated_mail(template_name, email_context, recipients, sender=None, bcc=None, fail_silently=False, files=None): +logger = logging.getLogger('helpdesk') + + +def send_templated_mail(template_name, + email_context, + recipients, + sender=None, + bcc=None, + fail_silently=False, + files=None): """ send_templated_mail() is a warpper around Django's e-mail routines that allows us to easily send multipart (text/plain & text/html) e-mails using @@ -46,7 +53,7 @@ def send_templated_mail(template_name, email_context, recipients, sender=None, b fail_silently is passed to Django's mail routine. Set to 'True' to ignore any errors at send time. - files can be a list of tuple. Each tuple should be a filename to attach, + files can be a list of tuple. Each tuple should be a filename to attach, along with the File objects to be read. files can be blank. """ @@ -56,7 +63,8 @@ def send_templated_mail(template_name, email_context, recipients, sender=None, b from django.template import loader, Context from helpdesk.models import EmailTemplate - from helpdesk.settings import HELPDESK_EMAIL_SUBJECT_TEMPLATE + from helpdesk.settings import HELPDESK_EMAIL_SUBJECT_TEMPLATE, \ + HELPDESK_EMAIL_FALLBACK_LOCALE import os # RemovedInDjango110Warning: render() must be called with a dict, not a Context. @@ -68,9 +76,9 @@ def send_templated_mail(template_name, email_context, recipients, sender=None, b if hasattr(context['queue'], 'locale'): locale = getattr(context['queue'], 'locale', '') else: - locale = context['queue'].get('locale', 'en') + locale = context['queue'].get('locale', HELPDESK_EMAIL_FALLBACK_LOCALE) if not locale: - locale = 'en' + locale = HELPDESK_EMAIL_FALLBACK_LOCALE t = None try: @@ -82,16 +90,17 @@ def send_templated_mail(template_name, email_context, recipients, sender=None, b try: t = EmailTemplate.objects.get(template_name__iexact=template_name, locale__isnull=True) except EmailTemplate.DoesNotExist: - logger.warning('template "%s" does not exist, no mail sent' % - template_name) - return # just ignore if template doesn't exist + logger.warning('template "%s" does not exist, no mail sent', + template_name) + return # just ignore if template doesn't exist if not sender: sender = settings.DEFAULT_FROM_EMAIL footer_file = os.path.join('helpdesk', locale, 'email_text_footer.txt') - - # get_template_from_string was removed in Django 1.8 http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html + + # get_template_from_string was removed in Django 1.8 + # http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html try: from django.template import engines template_func = engines['django'].from_string @@ -100,25 +109,26 @@ def send_templated_mail(template_name, email_context, recipients, sender=None, b text_part = template_func( "%s{%% include '%s' %%}" % (t.plain_text, footer_file) - ).render(context) + ).render(context) email_html_base_file = os.path.join('helpdesk', locale, 'email_html_base.html') - - ''' keep new lines in html emails ''' - from django.utils.safestring import mark_safe - + # keep new lines in html emails if 'comment' in context: html_txt = context['comment'] html_txt = html_txt.replace('\r\n', '
') context['comment'] = mark_safe(html_txt) - # get_template_from_string was removed in Django 1.8 http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html + # get_template_from_string was removed in Django 1.8 + # http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html html_part = template_func( - "{%% extends '%s' %%}{%% block title %%}%s{%% endblock %%}{%% block content %%}%s{%% endblock %%}" % (email_html_base_file, t.heading, t.html) - ).render(context) + "{%% extends '%s' %%}{%% block title %%}" + "%s" + "{%% endblock %%}{%% block content %%}%s{%% endblock %%}" % + (email_html_base_file, t.heading, t.html)).render(context) - # get_template_from_string was removed in Django 1.8 http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html + # get_template_from_string was removed in Django 1.8 + # http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html subject_part = template_func( HELPDESK_EMAIL_SUBJECT_TEMPLATE % { "subject": t.subject, @@ -128,13 +138,11 @@ def send_templated_mail(template_name, email_context, recipients, sender=None, b if recipients.find(','): recipients = recipients.split(',') elif type(recipients) != list: - recipients = [recipients,] + recipients = [recipients, ] - msg = EmailMultiAlternatives( subject_part.replace('\n', '').replace('\r', ''), - text_part, - sender, - recipients, - bcc=bcc) + msg = EmailMultiAlternatives( + subject_part.replace('\n', '').replace('\r', ''), + text_part, sender, recipients, bcc=bcc) msg.attach_alternative(html_part, "text/html") if files: @@ -178,7 +186,7 @@ def apply_query(queryset, params): params is a dictionary that contains the following: filtering: A dict of Django ORM filters, eg: {'user__id__in': [1, 3, 103], 'title__contains': 'foo'} - + search_string: A freetext search string sorting: The name of the column to sort by @@ -225,23 +233,23 @@ def safe_template_context(ticket): context = { 'queue': {}, - 'ticket': {}, - } + 'ticket': {} + } queue = ticket.queue - for field in ( 'title', 'slug', 'email_address', 'from_address', 'locale'): + for field in ('title', 'slug', 'email_address', 'from_address', 'locale'): attr = getattr(queue, field, None) if callable(attr): context['queue'][field] = attr() else: context['queue'][field] = attr - for field in ( 'title', 'created', 'modified', 'submitter_email', - 'status', 'get_status_display', 'on_hold', 'description', - 'resolution', 'priority', 'get_priority_display', - 'last_escalation', 'ticket', 'ticket_for_url', - 'get_status', 'ticket_url', 'staff_url', '_get_assigned_to' - ): + for field in ('title', 'created', 'modified', 'submitter_email', + 'status', 'get_status_display', 'on_hold', 'description', + 'resolution', 'priority', 'get_priority_display', + 'last_escalation', 'ticket', 'ticket_for_url', + 'get_status', 'ticket_url', 'staff_url', '_get_assigned_to' + ): attr = getattr(ticket, field, None) if callable(attr): context['ticket'][field] = '%s' % attr() @@ -277,10 +285,10 @@ def text_is_spam(text, request): ) if hasattr(settings, 'TYPEPAD_ANTISPAM_API_KEY'): - ak.setAPIKey(key = settings.TYPEPAD_ANTISPAM_API_KEY) + ak.setAPIKey(key=settings.TYPEPAD_ANTISPAM_API_KEY) ak.baseurl = 'api.antispam.typepad.com/1.1/' elif hasattr(settings, 'AKISMET_API_KEY'): - ak.setAPIKey(key = settings.AKISMET_API_KEY) + ak.setAPIKey(key=settings.AKISMET_API_KEY) else: return False diff --git a/helpdesk/locale/es_MX/LC_MESSAGES/django.mo b/helpdesk/locale/es_MX/LC_MESSAGES/django.mo index 50f7f103..8b1d9ed8 100644 Binary files a/helpdesk/locale/es_MX/LC_MESSAGES/django.mo and b/helpdesk/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/helpdesk/locale/es_MX/LC_MESSAGES/django.po b/helpdesk/locale/es_MX/LC_MESSAGES/django.po index 089990c6..9697d596 100644 --- a/helpdesk/locale/es_MX/LC_MESSAGES/django.po +++ b/helpdesk/locale/es_MX/LC_MESSAGES/django.po @@ -1,1069 +1,1171 @@ # django-helpdesk English language translation # Copyright (C) 2011 Ross Poulton # This file is distributed under the same license as the django-helpdesk package. -# +# +# Translators: # Translators: # Alberto Gaona , 2011 # Apizano , 2013 # Apizano , 2012 -# Erik Rivera , 2011,2013 +# Erik Rivera , 2011,2013,2016 # Ross Poulton , 2011 msgid "" msgstr "" "Project-Id-Version: django-helpdesk\n" "Report-Msgid-Bugs-To: http://github.com/RossP/django-helpdesk/issues\n" -"POT-Creation-Date: 2012-08-07 20:40+1000\n" -"PO-Revision-Date: 2013-04-29 09:18+0000\n" -"Last-Translator: Ross Poulton \n" -"Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/django-helpdesk/language/es_MX/)\n" +"POT-Creation-Date: 2014-07-26 14:14+0200\n" +"PO-Revision-Date: 2016-05-11 16:55+0000\n" +"Last-Translator: Erik Rivera \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/rossp/django-helpdesk/language/es_MX/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_MX\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: forms.py:113 forms.py:360 models.py:262 -#: templates/helpdesk/dashboard.html:11 templates/helpdesk/dashboard.html:37 -#: templates/helpdesk/dashboard.html:57 templates/helpdesk/dashboard.html:77 -#: templates/helpdesk/dashboard.html:99 templates/helpdesk/rss_list.html:23 -#: templates/helpdesk/ticket_list.html:56 -#: templates/helpdesk/ticket_list.html:78 -#: templates/helpdesk/ticket_list.html:199 views/staff.py:976 -#: views/staff.py:982 views/staff.py:988 +#: forms.py:128 forms.py:328 models.py:190 models.py:267 +#: templates/helpdesk/dashboard.html:15 templates/helpdesk/dashboard.html:58 +#: templates/helpdesk/dashboard.html:78 templates/helpdesk/dashboard.html:100 +#: templates/helpdesk/dashboard.html:124 templates/helpdesk/rss_list.html:24 +#: templates/helpdesk/ticket_list.html:69 +#: templates/helpdesk/ticket_list.html:88 +#: templates/helpdesk/ticket_list.html:225 views/staff.py:1032 +#: views/staff.py:1038 views/staff.py:1044 views/staff.py:1050 msgid "Queue" msgstr "Colas" -#: forms.py:122 +#: forms.py:137 msgid "Summary of the problem" msgstr "Resumen del problema" -#: forms.py:127 +#: forms.py:142 msgid "Submitter E-Mail Address" msgstr "E-Mail de Remitente" -#: forms.py:129 +#: forms.py:144 msgid "" "This e-mail address will receive copies of all public updates to this " "ticket." msgstr "Esta direccion de e-mail recibirá copias de todas las actualizaciones públicas de este ticket." -#: forms.py:135 +#: forms.py:150 msgid "Description of Issue" msgstr "Descripción del Problema" -#: forms.py:142 +#: forms.py:157 msgid "Case owner" msgstr "Dueño" -#: forms.py:143 +#: forms.py:158 msgid "" "If you select an owner other than yourself, they'll be e-mailed details of " "this ticket immediately." msgstr "Si selecciona un propietario que no sea usted, será notificado por correo acerca de este ticket inmediatamente" -#: forms.py:151 models.py:322 management/commands/escalate_tickets.py:149 -#: templates/helpdesk/public_view_ticket.html:21 -#: templates/helpdesk/ticket.html:176 -#: templates/helpdesk/ticket_desc_table.html:31 -#: templates/helpdesk/ticket_list.html:84 views/staff.py:355 +#: forms.py:166 models.py:327 management/commands/escalate_tickets.py:154 +#: templates/helpdesk/public_view_ticket.html:23 +#: templates/helpdesk/ticket.html:184 +#: templates/helpdesk/ticket_desc_table.html:47 +#: templates/helpdesk/ticket_list.html:94 views/staff.py:429 msgid "Priority" msgstr "Prioridad" -#: forms.py:152 +#: forms.py:167 msgid "Please select a priority carefully. If unsure, leave it as '3'." msgstr "Por favor seleccione cuidadosamente una prioridad. Si no está seguro, déjelo como está (3)." -#: forms.py:159 forms.py:397 models.py:330 templates/helpdesk/ticket.html:178 -#: views/staff.py:365 +#: forms.py:174 forms.py:365 models.py:335 templates/helpdesk/ticket.html:186 +#: views/staff.py:439 msgid "Due on" msgstr "Se requiere solución para el día" -#: forms.py:171 forms.py:402 +#: forms.py:186 forms.py:370 msgid "Attach File" msgstr "Adjuntar Archivo." -#: forms.py:172 forms.py:403 +#: forms.py:187 forms.py:371 msgid "You can attach a file such as a document or screenshot to this ticket." msgstr "Usted puede adjuntar un archivo como documento o una captura de pantalla a este ticket." -#: forms.py:180 templates/helpdesk/public_view_ticket.html:33 -#: templates/helpdesk/ticket.html:182 -#: templates/helpdesk/ticket_desc_table.html:42 -#: templates/helpdesk/ticket_list.html:61 -#: templates/helpdesk/ticket_list.html:199 views/staff.py:376 -msgid "Tags" -msgstr "Etiquetas" - -#: forms.py:181 -msgid "" -"Words, separated by spaces, or phrases separated by commas. These should " -"communicate significant characteristics of this ticket" -msgstr "Palabras, separadas por espacios o frases separadas por comas. Estás representaran características significativas a este ticket." - -#: forms.py:275 +#: forms.py:240 msgid "Ticket Opened" msgstr "Ticket abierto" -#: forms.py:282 +#: forms.py:247 #, python-format msgid "Ticket Opened & Assigned to %(name)s" msgstr "Ticket abierto & Asignado a %(name)s" -#: forms.py:369 +#: forms.py:337 msgid "Summary of your query" msgstr "Resumen de su consulta" -#: forms.py:374 +#: forms.py:342 msgid "Your E-Mail Address" msgstr "Su dirección de e-mail" -#: forms.py:375 +#: forms.py:343 msgid "We will e-mail you when your ticket is updated." msgstr "Le enviaremos un e-mail cuando su ticket se actualice." -#: forms.py:380 +#: forms.py:348 msgid "Description of your issue" msgstr "Descripción del problema" -#: forms.py:382 +#: forms.py:350 msgid "" "Please be as descriptive as possible, including any details we may need to " "address your query." msgstr "Por favor sea lo más descriptivo posible, incluyendo cualquier información necesaria para resolver pronto su problema." -#: forms.py:390 +#: forms.py:358 msgid "Urgency" msgstr "Urgencia" -#: forms.py:391 +#: forms.py:359 msgid "Please select a priority carefully." msgstr "Por favor seleccione una prioridad cuidadosamente." -#: forms.py:486 +#: forms.py:419 msgid "Ticket Opened Via Web" msgstr "Ticket abierto vía web" -#: forms.py:553 +#: forms.py:486 msgid "Show Ticket List on Login?" msgstr "¿Mostrar la lista de tickets al entrar?" -#: forms.py:554 +#: forms.py:487 msgid "Display the ticket list upon login? Otherwise, the dashboard is shown." msgstr "¿Mostar la lista de ticket después de ingresar? De otra forma, el dashboard será mostrado." -#: forms.py:559 +#: forms.py:492 msgid "E-mail me on ticket change?" msgstr "Envíenme un mensaje cuando cambie el ticket" -#: forms.py:560 +#: forms.py:493 msgid "" "If you're the ticket owner and the ticket is changed via the web by somebody" " else, do you want to receive an e-mail?" msgstr "¿Quiere recibir un e-mail si usted es el dueño de un ticket y el ticket es cambiado vía web por alguien más?" -#: forms.py:565 +#: forms.py:498 msgid "E-mail me when assigned a ticket?" msgstr "¿Enviarle un correo cuando se le asigne un ticket?" -#: forms.py:566 +#: forms.py:499 msgid "" "If you are assigned a ticket via the web, do you want to receive an e-mail?" msgstr "¿Quiere que se le envie un e-mail si se le asigna un ticket via web?" -#: forms.py:571 +#: forms.py:504 msgid "E-mail me when a ticket is changed via the API?" msgstr "¿Enviarle un correo si un ticket es cambiado vía el API?" -#: forms.py:572 +#: forms.py:505 msgid "If a ticket is altered by the API, do you want to receive an e-mail?" msgstr "¿Quiere recibir un e-mail si un ticket es modificado a través de la API?" -#: forms.py:577 +#: forms.py:510 msgid "Number of tickets to show per page" msgstr "Número de tickets a mostrar por página" -#: forms.py:578 +#: forms.py:511 msgid "How many tickets do you want to see on the Ticket List page?" msgstr "¿Cuántos tickets quiere ver en la página de Lista de Tickets?" -#: forms.py:585 +#: forms.py:518 msgid "Use my e-mail address when submitting tickets?" msgstr "¿Usar mi direccion de e-mail cuando se envien tickets?" -#: forms.py:586 +#: forms.py:519 msgid "" "When you submit a ticket, do you want to automatically use your e-mail " "address as the submitter address? You can type a different e-mail address " "when entering the ticket if needed, this option only changes the default." msgstr "Cuando envia un ticket, ¿quiere que automáticamente se use su dirección de e-mail como emisor? Usted puede ingresar una dirección de e-mail cuando se ingrese un ticket si es que lo necesita. Esta opción solo modifica la opción por defecto." -#: models.py:32 models.py:256 models.py:490 models.py:787 models.py:821 -#: templates/helpdesk/dashboard.html:37 templates/helpdesk/dashboard.html:57 -#: templates/helpdesk/dashboard.html:77 templates/helpdesk/dashboard.html:99 -#: templates/helpdesk/ticket.html:170 templates/helpdesk/ticket_list.html:75 -#: templates/helpdesk/ticket_list.html:199 views/staff.py:345 +#: models.py:35 models.py:261 models.py:503 models.py:817 models.py:853 +#: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 +#: templates/helpdesk/dashboard.html:100 templates/helpdesk/dashboard.html:124 +#: templates/helpdesk/ticket.html:178 templates/helpdesk/ticket_list.html:85 +#: templates/helpdesk/ticket_list.html:225 views/staff.py:419 msgid "Title" msgstr "Título" -#: models.py:37 models.py:792 models.py:1162 +#: models.py:40 models.py:822 models.py:1206 msgid "Slug" msgstr "Prefijo" -#: models.py:38 +#: models.py:41 msgid "" "This slug is used when building ticket ID's. Once set, try not to change it " "or e-mailing may get messy." msgstr "Este prefijo es utilizado como parte del ID de un ticket. Una vez configurado, trate de no cambiarlo o las notificaciones e-mail pueden dejar de funcionar." -#: models.py:43 models.py:1015 models.py:1085 models.py:1159 +#: models.py:46 models.py:1054 models.py:1129 models.py:1203 #: templates/helpdesk/email_ignore_list.html:13 #: templates/helpdesk/ticket_cc_list.html:15 msgid "E-Mail Address" msgstr "Dirección de E-mail" -#: models.py:46 +#: models.py:49 msgid "" "All outgoing e-mails for this queue will use this e-mail address. If you use" " IMAP or POP3, this should be the e-mail address for that mailbox." msgstr "Todos los correos de salida de esta cola usarán esta dirección. Si usa IMAP o POP3, esta debe ser la dirección de correo para ese buzón" -#: models.py:52 models.py:766 +#: models.py:55 models.py:794 msgid "Locale" msgstr "Internacionalización" -#: models.py:56 +#: models.py:59 msgid "" "Locale of this queue. All correspondence in this queue will be in this " "language." msgstr "Internacionalización de esta cola. Todo lo que corresponda a esta cola estara en este lenguaje." -#: models.py:60 +#: models.py:63 msgid "Allow Public Submission?" msgstr "¿Permitir envíos públicos?" -#: models.py:63 +#: models.py:66 msgid "Should this queue be listed on the public submission form?" msgstr "¿Debe esta cola ser listada en el formulario de envíos públicos?" -#: models.py:68 +#: models.py:71 msgid "Allow E-Mail Submission?" msgstr "¿Permitir envíos por e-mail?" -#: models.py:71 +#: models.py:74 msgid "Do you want to poll the e-mail box below for new tickets?" msgstr "¿Quiere sondear el buzón de correo de abajo para nuevos tickets?" -#: models.py:76 +#: models.py:79 msgid "Escalation Days" msgstr "Dias de escalamiento" -#: models.py:79 +#: models.py:82 msgid "" "For tickets which are not held, how often do you wish to increase their " "priority? Set to 0 for no escalation." msgstr "¿con que frecuencia desea incrementar la prioridad de los tickets que no están retenidos? Especifique 0 para que no existan escalamientos." -#: models.py:84 +#: models.py:87 msgid "New Ticket CC Address" msgstr "Dirección CC Nuevo Ticket" -#: models.py:88 +#: models.py:91 msgid "" "If an e-mail address is entered here, then it will receive notification of " "all new tickets created for this queue. Enter a comma between multiple " "e-mail addresses." msgstr "Si introduce una dirección de e-mail aquí dicha dirección recibirá notificaciones de los nuevos tickets creados para esta cola. Introduzca una coma entre múltiples direcciones de e-mail." -#: models.py:94 +#: models.py:97 msgid "Updated Ticket CC Address" msgstr "Actualización de Ticket, Dirección de CC" -#: models.py:98 +#: models.py:101 msgid "" "If an e-mail address is entered here, then it will receive notification of " "all activity (new tickets, closed tickets, updates, reassignments, etc) for " "this queue. Separate multiple addresses with a comma." msgstr "Si introduce una dirección de e-mail aquí dicha dirección recibirá notificaciones de los nuevos tickets creados para esta cola. Introduzca una coma entre múltiples direcciones de e-mail." -#: models.py:105 +#: models.py:108 msgid "E-Mail Box Type" msgstr "Tipo de buzón de correo" -#: models.py:107 +#: models.py:110 msgid "POP 3" msgstr "POP 3" -#: models.py:107 +#: models.py:110 msgid "IMAP" msgstr "IMAP" -#: models.py:110 +#: models.py:113 msgid "" "E-Mail server type for creating tickets automatically from a mailbox - both " "POP3 and IMAP are supported." msgstr "Dirección de correo para crear tickets automáticos a partir de un buzón de correo, tanto POP3 e IMAP son soportados." -#: models.py:115 +#: models.py:118 msgid "E-Mail Hostname" msgstr "Servidor de e-mail" -#: models.py:119 +#: models.py:122 msgid "" "Your e-mail server address - either the domain name or IP address. May be " "\"localhost\"." msgstr "La dirección IP o nombre de dominio de su servidor de e-mail. Puede ser \"localhost\"." -#: models.py:124 +#: models.py:127 msgid "E-Mail Port" msgstr "Puerto de e-mail" -#: models.py:127 +#: models.py:130 msgid "" "Port number to use for accessing e-mail. Default for POP3 is \"110\", and " "for IMAP is \"143\". This may differ on some servers. Leave it blank to use " "the defaults." msgstr "Número de puerto para acceder a e-mail. Por defecto POP3 es \"110\" y para IMAP es \"143\". Esto puede ser distinto en algunos servidores. Deje en blanco para usar los por defecto." -#: models.py:133 +#: models.py:136 msgid "Use SSL for E-Mail?" msgstr "¿Usar SSL para el e-mail?" -#: models.py:136 +#: models.py:139 msgid "" "Whether to use SSL for IMAP or POP3 - the default ports when using SSL are " "993 for IMAP and 995 for POP3." msgstr "Si va a utilizar SSL para IMAP o POP3 - el puerto predeterminado es 993 para IMAP y 995 para POP3" -#: models.py:141 +#: models.py:144 msgid "E-Mail Username" msgstr "Nombre de usuario de e-mail" -#: models.py:145 +#: models.py:148 msgid "Username for accessing this mailbox." msgstr "Nombre de usuario para accesar esta casilla." -#: models.py:149 +#: models.py:152 msgid "E-Mail Password" msgstr "Contraseña de e-mail" -#: models.py:153 +#: models.py:156 msgid "Password for the above username" msgstr "Contraseña para el usuario de encima" -#: models.py:157 +#: models.py:160 msgid "IMAP Folder" msgstr "Carpeta IMAP" -#: models.py:161 +#: models.py:164 msgid "" "If using IMAP, what folder do you wish to fetch messages from? This allows " "you to use one IMAP account for multiple queues, by filtering messages on " "your IMAP server into separate folders. Default: INBOX." msgstr "Si utiliza IMAP ¿de qué carpeta quiere extraer los mensajes? Esta característica le permite utilizar una sola cuenta IMAP para varias colas, filtrando los mensajes en el servidor IMAP y colocándolos en diferentes carpetas. Default: INBOX" -#: models.py:168 +#: models.py:171 msgid "E-Mail Check Interval" msgstr "Intervalo de revisión de correo" -#: models.py:169 +#: models.py:172 msgid "How often do you wish to check this mailbox? (in Minutes)" msgstr "¿Con que frecuencia desea revisar el buzón de correo? (En Minutos)" -#: models.py:240 templates/helpdesk/dashboard.html:11 -#: templates/helpdesk/ticket.html:130 +#: models.py:191 templates/helpdesk/email_ignore_list.html:13 +msgid "Queues" +msgstr "Departamentos" + +#: models.py:245 templates/helpdesk/dashboard.html:15 +#: templates/helpdesk/ticket.html:138 msgid "Open" msgstr "Abierto" -#: models.py:241 templates/helpdesk/ticket.html:136 -#: templates/helpdesk/ticket.html.py:142 templates/helpdesk/ticket.html:147 -#: templates/helpdesk/ticket.html.py:151 +#: models.py:246 templates/helpdesk/ticket.html:144 +#: templates/helpdesk/ticket.html.py:150 templates/helpdesk/ticket.html:155 +#: templates/helpdesk/ticket.html.py:159 msgid "Reopened" msgstr "Reabierto" -#: models.py:242 templates/helpdesk/dashboard.html:11 -#: templates/helpdesk/ticket.html:131 templates/helpdesk/ticket.html.py:137 -#: templates/helpdesk/ticket.html:143 +#: models.py:247 templates/helpdesk/dashboard.html:15 +#: templates/helpdesk/ticket.html:139 templates/helpdesk/ticket.html.py:145 +#: templates/helpdesk/ticket.html:151 msgid "Resolved" msgstr "Resuelto" -#: models.py:243 templates/helpdesk/dashboard.html:11 -#: templates/helpdesk/ticket.html:132 templates/helpdesk/ticket.html.py:138 -#: templates/helpdesk/ticket.html:144 templates/helpdesk/ticket.html.py:148 +#: models.py:248 templates/helpdesk/dashboard.html:15 +#: templates/helpdesk/ticket.html:140 templates/helpdesk/ticket.html.py:146 +#: templates/helpdesk/ticket.html:152 templates/helpdesk/ticket.html.py:156 msgid "Closed" msgstr "Cerrado" -#: models.py:244 templates/helpdesk/ticket.html:133 -#: templates/helpdesk/ticket.html.py:139 templates/helpdesk/ticket.html:152 +#: models.py:249 templates/helpdesk/ticket.html:141 +#: templates/helpdesk/ticket.html.py:147 templates/helpdesk/ticket.html:160 msgid "Duplicate" msgstr "Duplicado" -#: models.py:248 +#: models.py:253 msgid "1. Critical" msgstr "1. Crítico" -#: models.py:249 +#: models.py:254 msgid "2. High" msgstr "2. Alto" -#: models.py:250 +#: models.py:255 msgid "3. Normal" msgstr "3. Normal" -#: models.py:251 +#: models.py:256 msgid "4. Low" msgstr "4. Bajo" -#: models.py:252 +#: models.py:257 msgid "5. Very Low" msgstr "5. Muy bajo" -#: models.py:266 templates/helpdesk/dashboard.html:77 -#: templates/helpdesk/ticket_list.html:72 -#: templates/helpdesk/ticket_list.html:199 +#: models.py:271 templates/helpdesk/dashboard.html:100 +#: templates/helpdesk/ticket_list.html:82 +#: templates/helpdesk/ticket_list.html:225 msgid "Created" msgstr "Creado" -#: models.py:268 +#: models.py:273 msgid "Date this ticket was first created" msgstr "Fecha de cuando fue creado este ticket" -#: models.py:272 +#: models.py:277 msgid "Modified" msgstr "Modificado" -#: models.py:274 +#: models.py:279 msgid "Date this ticket was most recently changed." msgstr "Fecha de cuando fue reciente modifcado este ticket" -#: models.py:278 templates/helpdesk/public_view_ticket.html:16 -#: templates/helpdesk/ticket_desc_table.html:26 +#: models.py:283 templates/helpdesk/public_view_ticket.html:18 +#: templates/helpdesk/ticket_desc_table.html:42 msgid "Submitter E-Mail" msgstr "E-mail del solicitante" -#: models.py:281 +#: models.py:286 msgid "" "The submitter will receive an email for all public follow-ups left for this " "task." msgstr "El solicitante recibira un e-mail para todas las actualizaciones publicas dejadas para esta tarea." -#: models.py:290 +#: models.py:295 msgid "Assigned to" msgstr "Asignado a" -#: models.py:294 templates/helpdesk/dashboard.html:37 -#: templates/helpdesk/dashboard.html:57 templates/helpdesk/dashboard.html:99 -#: templates/helpdesk/ticket_list.html:57 -#: templates/helpdesk/ticket_list.html:81 -#: templates/helpdesk/ticket_list.html:199 +#: models.py:299 templates/helpdesk/dashboard.html:58 +#: templates/helpdesk/dashboard.html:78 templates/helpdesk/dashboard.html:124 +#: templates/helpdesk/ticket_list.html:70 +#: templates/helpdesk/ticket_list.html:91 +#: templates/helpdesk/ticket_list.html:225 msgid "Status" msgstr "Estado" -#: models.py:300 +#: models.py:305 msgid "On Hold" msgstr "Mantener" -#: models.py:303 +#: models.py:308 msgid "If a ticket is on hold, it will not automatically be escalated." msgstr "Si un ticket es mantenido, no sera automaticamente escalado." -#: models.py:308 models.py:796 templates/helpdesk/public_view_ticket.html:39 -#: templates/helpdesk/ticket_desc_table.html:67 +#: models.py:313 models.py:826 templates/helpdesk/public_view_ticket.html:41 +#: templates/helpdesk/ticket_desc_table.html:19 msgid "Description" msgstr "Descripcion" -#: models.py:311 +#: models.py:316 msgid "The content of the customers query." msgstr "El contenido de la consulta de clientes" -#: models.py:315 templates/helpdesk/public_view_ticket.html:46 -#: templates/helpdesk/ticket_desc_table.html:74 +#: models.py:320 templates/helpdesk/public_view_ticket.html:48 +#: templates/helpdesk/ticket_desc_table.html:26 msgid "Resolution" msgstr "Resolución" -#: models.py:318 +#: models.py:323 msgid "The resolution provided to the customer by our staff." msgstr "La resolución proporcionada al cliente por el personal" -#: models.py:326 +#: models.py:331 msgid "1 = Highest Priority, 5 = Low Priority" msgstr "1 = Prioridad mas alta, 5 = Prioridad Baja" -#: models.py:339 +#: models.py:344 msgid "" "The date this ticket was last escalated - updated automatically by " "management/commands/escalate_tickets.py." msgstr "La fecha de este ticket fue modificada por la ultima escalación - actualizado automáticamente por management/commands/escalate_tickets.py." -#: models.py:348 templates/helpdesk/ticket_desc_table.html:22 -#: views/feeds.py:91 views/feeds.py:117 views/feeds.py:169 views/staff.py:302 +#: models.py:353 templates/helpdesk/ticket_desc_table.html:38 +#: views/feeds.py:95 views/feeds.py:121 views/feeds.py:173 views/staff.py:376 msgid "Unassigned" msgstr "Sin Asignar" -#: models.py:387 +#: models.py:392 msgid " - On Hold" msgstr "En Espera" -#: models.py:481 models.py:1073 models.py:1231 models.py:1256 -#: templates/helpdesk/public_homepage.html:26 +#: models.py:394 +msgid " - Open dependencies" +msgstr "Dependencias abiertas" + +#: models.py:448 models.py:494 models.py:1117 models.py:1280 models.py:1309 +#: templates/helpdesk/public_homepage.html:78 #: templates/helpdesk/public_view_form.html:12 msgid "Ticket" msgstr "Ticket" -#: models.py:485 models.py:714 models.py:1008 models.py:1156 +#: models.py:449 templates/helpdesk/navigation.html:17 +#: templates/helpdesk/ticket_list.html:2 +#: templates/helpdesk/ticket_list.html:224 +msgid "Tickets" +msgstr "Tickets" + +#: models.py:498 models.py:738 models.py:1047 models.py:1200 msgid "Date" msgstr "Fecha" -#: models.py:497 views/staff.py:316 +#: models.py:510 views/staff.py:390 msgid "Comment" msgstr "Comentario" -#: models.py:503 +#: models.py:516 msgid "Public" msgstr "Público" -#: models.py:506 +#: models.py:519 msgid "" "Public tickets are viewable by the submitter and all staff, but non-public " "tickets can only be seen by staff." msgstr "Los tickets públicos son visibles por el usuario y todo el personal, pero las entradas no pública sólo pueden ser vistos por el personal." -#: models.py:514 models.py:888 models.py:1081 views/staff.py:952 -#: views/staff.py:958 views/staff.py:964 views/staff.py:970 +#: models.py:527 models.py:922 models.py:1125 views/staff.py:1008 +#: views/staff.py:1014 views/staff.py:1020 views/staff.py:1026 msgid "User" msgstr "Usuario" -#: models.py:518 templates/helpdesk/ticket.html:127 +#: models.py:531 templates/helpdesk/ticket.html:135 msgid "New Status" msgstr "Nuevo Estado" -#: models.py:522 +#: models.py:535 msgid "If the status was changed, what was it changed to?" msgstr "Si el estado cambió, ¿que fue a lo que cambió?" -#: models.py:551 models.py:608 +#: models.py:542 models.py:566 models.py:628 msgid "Follow-up" msgstr "Seguimiento" -#: models.py:555 models.py:1236 +#: models.py:543 +msgid "Follow-ups" +msgstr "Seguimientos" + +#: models.py:570 models.py:1285 msgid "Field" msgstr "Campo" -#: models.py:560 +#: models.py:575 msgid "Old Value" msgstr "Valor Viejo" -#: models.py:566 +#: models.py:581 msgid "New Value" msgstr "Valor nuevo" -#: models.py:574 +#: models.py:589 msgid "removed" msgstr "removido" -#: models.py:576 +#: models.py:591 #, python-format msgid "set to %s" msgstr "establece en %s" -#: models.py:578 +#: models.py:593 #, python-format msgid "changed from \"%(old_value)s\" to \"%(new_value)s\"" msgstr "cambiado de \"%(old_value)s\" a \"%(new_value)s\"" -#: models.py:612 +#: models.py:600 +msgid "Ticket change" +msgstr "" + +#: models.py:601 +msgid "Ticket changes" +msgstr "" + +#: models.py:632 msgid "File" msgstr "Archivo" -#: models.py:617 +#: models.py:637 msgid "Filename" msgstr "Nombre de Archivo" -#: models.py:622 +#: models.py:642 msgid "MIME Type" msgstr "Tipo MIME" -#: models.py:627 +#: models.py:647 msgid "Size" msgstr "Tamaño" -#: models.py:628 +#: models.py:648 msgid "Size of this file in bytes" msgstr "Tamaño del archivo en bytes" -#: models.py:663 +#: models.py:665 +msgid "Attachment" +msgstr "" + +#: models.py:666 +msgid "Attachments" +msgstr "" + +#: models.py:685 msgid "" "Leave blank to allow this reply to be used for all queues, or select those " "queues you wish to limit this reply to." msgstr "Dejar en blanco para permitir que esta respuesta que se utilizará para todas las colas, o seleccionar las colas desea limitar esta respuesta." -#: models.py:668 models.py:709 models.py:1003 +#: models.py:690 models.py:733 models.py:1042 #: templates/helpdesk/email_ignore_list.html:13 msgid "Name" msgstr "Nombre" -#: models.py:670 +#: models.py:692 msgid "" "Only used to assist users with selecting a reply - not shown to the user." msgstr "Sólo se utiliza para ayudar a los usuarios con la selección de una respuesta - no se muestra al usuario." -#: models.py:675 +#: models.py:697 msgid "Body" msgstr "Cuerpo" -#: models.py:676 +#: models.py:698 msgid "" "Context available: {{ ticket }} - ticket object (eg {{ ticket.title }}); {{ " "queue }} - The queue; and {{ user }} - the current user." msgstr "Contexto: {{ ticket }} - ticket de objeto (por ejemplo, {{ ticket.title }}); {{ queue }} - La cola, y {{ user }} - el usuario actual." -#: models.py:703 +#: models.py:705 +msgid "Pre-set reply" +msgstr "" + +#: models.py:706 +msgid "Pre-set replies" +msgstr "" + +#: models.py:727 msgid "" "Leave blank for this exclusion to be applied to all queues, or select those " "queues you wish to exclude with this entry." msgstr "Deja en blanco para esta exclusión se aplica a todas las colas, o seleccionar las colas que desee excluir con esta entrada." -#: models.py:715 +#: models.py:739 msgid "Date on which escalation should not happen" msgstr "Fecha en la que la escalada no debe suceder" -#: models.py:732 +#: models.py:746 +msgid "Escalation exclusion" +msgstr "" + +#: models.py:747 +msgid "Escalation exclusions" +msgstr "" + +#: models.py:760 msgid "Template Name" msgstr "Nombre de Plantillla" -#: models.py:737 +#: models.py:765 msgid "Subject" msgstr "Asunto" -#: models.py:739 +#: models.py:767 msgid "" "This will be prefixed with \"[ticket.ticket] ticket.title\". We recommend " "something simple such as \"(Updated\") or \"(Closed)\" - the same context is" " available as in plain_text, below." msgstr "Este será el prefijo \"[ticket.ticket] ticket.title\". Se recomienda algo simple como \"(Actualización\") o \"(cerrado)\" - el mismo contexto se encuentra disponible como en plain_text, a continuación." -#: models.py:745 +#: models.py:773 msgid "Heading" msgstr "Encabezado" -#: models.py:747 +#: models.py:775 msgid "" "In HTML e-mails, this will be the heading at the top of the email - the same" " context is available as in plain_text, below." msgstr "En correos HTML, este será el encabezado al principio del correo - el mismo contexto aplica a textlo plano, abajo." -#: models.py:753 +#: models.py:781 msgid "Plain Text" msgstr "Texto Plano" -#: models.py:754 +#: models.py:782 msgid "" "The context available to you includes {{ ticket }}, {{ queue }}, and " "depending on the time of the call: {{ resolution }} or {{ comment }}." msgstr "El contexto a su disposición incluye {{ ticket }}, {{ queue }}, y dependiendo de la hora de la llamada: {{resolution}} o {{comment}}." -#: models.py:760 +#: models.py:788 msgid "HTML" msgstr "HTML" -#: models.py:761 +#: models.py:789 msgid "The same context is available here as in plain_text, above." msgstr "El mismo contexto está disponible aquí como texto plano, arriba." -#: models.py:770 +#: models.py:798 msgid "Locale of this template." msgstr "Locale de esta plantilla" -#: models.py:817 templates/helpdesk/kb_index.html:10 -#: templates/helpdesk/public_homepage.html:10 +#: models.py:806 +msgid "e-mail template" +msgstr "" + +#: models.py:807 +msgid "e-mail templates" +msgstr "" + +#: models.py:834 +msgid "Knowledge base category" +msgstr "" + +#: models.py:835 +msgid "Knowledge base categories" +msgstr "" + +#: models.py:849 templates/helpdesk/kb_index.html:11 +#: templates/helpdesk/public_homepage.html:11 msgid "Category" msgstr "Categoría" -#: models.py:826 +#: models.py:858 msgid "Question" msgstr "Pregunta" -#: models.py:830 +#: models.py:862 msgid "Answer" msgstr "Respuesta" -#: models.py:834 +#: models.py:866 msgid "Votes" msgstr "Votos" -#: models.py:835 +#: models.py:867 msgid "Total number of votes cast for this item" msgstr "Número total de votos emitidos para este item" -#: models.py:840 +#: models.py:872 msgid "Positive Votes" msgstr "Votos positivos" -#: models.py:841 +#: models.py:873 msgid "Number of votes for this item which were POSITIVE." msgstr "Número total de votos para este item que fueron POSITIVOS" -#: models.py:846 +#: models.py:878 msgid "Last Updated" msgstr "Última actualización" -#: models.py:847 +#: models.py:879 msgid "The date on which this question was most recently changed." msgstr "La fecha en que esta cuestión fue recientemente cambiado." -#: models.py:861 +#: models.py:893 msgid "Unrated" msgstr "No calificado" -#: models.py:892 templates/helpdesk/ticket_list.html:158 +#: models.py:901 +msgid "Knowledge base item" +msgstr "" + +#: models.py:902 +msgid "Knowledge base items" +msgstr "" + +#: models.py:926 templates/helpdesk/ticket_list.html:170 msgid "Query Name" msgstr "Nombre de consulta" -#: models.py:894 +#: models.py:928 msgid "User-provided name for this query" msgstr "nombre proveido por el usuario para esta consulta" -#: models.py:898 +#: models.py:932 msgid "Shared With Other Users?" msgstr "¿Compartir con otros usuarios?" -#: models.py:901 +#: models.py:935 msgid "Should other users see this query?" msgstr "¿Deberían otros usuarios ver esta consulta?" -#: models.py:905 +#: models.py:939 msgid "Search Query" msgstr "Consulta de búsqueda" -#: models.py:906 +#: models.py:940 msgid "Pickled query object. Be wary changing this." msgstr "objeto de consulta en crudo. Tenga cuidado con cambiar esto." -#: models.py:927 +#: models.py:950 +msgid "Saved search" +msgstr "" + +#: models.py:951 +msgid "Saved searches" +msgstr "" + +#: models.py:966 msgid "Settings Dictionary" msgstr "Diccionario de Configuración" -#: models.py:928 +#: models.py:967 msgid "" "This is a base64-encoded representation of a pickled Python dictionary. Do " "not change this field via the admin." msgstr "Esta es una representación codificada en base 64 de un diccionario de Python en crudo. No cambie este campo a través de la administración." -#: models.py:997 +#: models.py:993 +msgid "User Setting" +msgstr "" + +#: models.py:994 templates/helpdesk/navigation.html:37 +#: templates/helpdesk/user_settings.html:6 +msgid "User Settings" +msgstr "Configuracion del Usuario" + +#: models.py:1036 msgid "" "Leave blank for this e-mail to be ignored on all queues, or select those " "queues you wish to ignore this e-mail for." msgstr "Deja en blanco para este e-mail para ser ignorado en todas las colas, o seleccionar las colas que desea ignorar este e-mail para." -#: models.py:1009 +#: models.py:1048 msgid "Date on which this e-mail address was added" msgstr "Fecha en la que se añadió la dirección de correo electrónico" -#: models.py:1017 +#: models.py:1056 msgid "" "Enter a full e-mail address, or portions with wildcards, eg *@domain.com or " "postmaster@*." msgstr "Introduzca una dirección de correo electrónico completa, o partes con comodines, por ejemplo, *@domain.com o postmaster@*." -#: models.py:1022 +#: models.py:1061 msgid "Save Emails in Mailbox?" msgstr "Guardar mensajes de correo electrónico en el buzón?" -#: models.py:1025 +#: models.py:1064 msgid "" "Do you want to save emails from this address in the mailbox? If this is " "unticked, emails from this address will be deleted." msgstr "¿Desea guardar los correos electrónicos de esta dirección en el buzón de correo? Si es marcada, los mensajes de correo electrónico de esta dirección serán eliminados." -#: models.py:1080 +#: models.py:1101 +msgid "Ignored e-mail address" +msgstr "" + +#: models.py:1102 +msgid "Ignored e-mail addresses" +msgstr "" + +#: models.py:1124 msgid "User who wishes to receive updates for this ticket." msgstr "Usuario que desea recibir las actualizaciones de este ticket." -#: models.py:1088 +#: models.py:1132 msgid "For non-user followers, enter their e-mail address" msgstr "Para los seguidores sin usuario, introduzca su dirección de correo electrónico" -#: models.py:1092 +#: models.py:1136 msgid "Can View Ticket?" msgstr "¿Puede ver el ticket?" -#: models.py:1094 +#: models.py:1138 msgid "Can this CC login to view the ticket details?" msgstr "¿Puede este CC entrar para ver los detalles del ticket?" -#: models.py:1098 +#: models.py:1142 msgid "Can Update Ticket?" msgstr "¿Puede actualizar el ticket?" -#: models.py:1100 +#: models.py:1144 msgid "Can this CC login and update the ticket?" msgstr "¿Puede este CC entrar y actualizar el ticket?" -#: models.py:1131 +#: models.py:1175 msgid "Field Name" msgstr "Nombre del campo" -#: models.py:1132 +#: models.py:1176 msgid "" "As used in the database and behind the scenes. Must be unique and consist of" " only lowercase letters with no punctuation." msgstr "Tal y como se usa en la base de datos del sistema. Debe ser único y consistir solo de minúsculas, sin puntos ni comas." -#: models.py:1137 +#: models.py:1181 msgid "Label" msgstr "Etiqueta" -#: models.py:1139 +#: models.py:1183 msgid "The display label for this field" msgstr "La etiqueta a desplegar para este campo" -#: models.py:1143 +#: models.py:1187 msgid "Help Text" msgstr "Texto de ayuda" -#: models.py:1144 +#: models.py:1188 msgid "Shown to the user when editing the ticket" msgstr "Se muestra al usuario cuando se edita el ticket" -#: models.py:1150 +#: models.py:1194 msgid "Character (single line)" msgstr "Caracter (una sola línea)" -#: models.py:1151 +#: models.py:1195 msgid "Text (multi-line)" msgstr "Texto (multi-línea)" -#: models.py:1152 +#: models.py:1196 msgid "Integer" msgstr "Entero" -#: models.py:1153 +#: models.py:1197 msgid "Decimal" msgstr "Decimal" -#: models.py:1154 +#: models.py:1198 msgid "List" msgstr "Lista" -#: models.py:1155 +#: models.py:1199 msgid "Boolean (checkbox yes/no)" msgstr "Booleano (checkbox sí/no)" -#: models.py:1157 +#: models.py:1201 msgid "Time" msgstr "Hora" -#: models.py:1158 +#: models.py:1202 msgid "Date & Time" msgstr "Fecha y hora" -#: models.py:1160 +#: models.py:1204 msgid "URL" msgstr "URL" -#: models.py:1161 +#: models.py:1205 msgid "IP Address" msgstr "Dirección IP" -#: models.py:1166 +#: models.py:1210 msgid "Data Type" msgstr "Tipo de dato" -#: models.py:1168 +#: models.py:1212 msgid "Allows you to restrict the data entered into this field" msgstr "Le permite restringir la información introducida en este campo" -#: models.py:1173 +#: models.py:1217 msgid "Maximum Length (characters)" msgstr "Longitud máxima (caracteres)" -#: models.py:1179 +#: models.py:1223 msgid "Decimal Places" msgstr "Lugares decimales" -#: models.py:1180 +#: models.py:1224 msgid "Only used for decimal fields" msgstr "Solo utilizado en campos decimales" -#: models.py:1186 +#: models.py:1230 msgid "Add empty first choice to List?" msgstr "Añadir una opción en blanco al inicio de la Lista?" -#: models.py:1187 +#: models.py:1232 msgid "" "Only for List: adds an empty first entry to the choices list, which enforces" " that the user makes an active choice." msgstr "Solo para Lista: Añadir una primera entrada vacía a las listas de opciones, para obligar que el usuario elija una opción activa." -#: models.py:1191 +#: models.py:1236 msgid "List Values" msgstr "Listas de valores" -#: models.py:1192 +#: models.py:1237 msgid "For list fields only. Enter one option per line." msgstr "Para campos de lista. Introduzca una opción por línea." -#: models.py:1198 +#: models.py:1243 msgid "Ordering" msgstr "Orden" -#: models.py:1199 +#: models.py:1244 msgid "Lower numbers are displayed first; higher numbers are listed later" msgstr "Los números mas pequeños son mostrados primero; los números más grandes se muestran al final" -#: models.py:1213 +#: models.py:1258 msgid "Required?" msgstr "¿Requerido?" -#: models.py:1214 +#: models.py:1259 msgid "Does the user have to enter a value for this field?" msgstr "¿El usuario está obligado a introducir un valor en este campo?" -#: models.py:1218 +#: models.py:1263 msgid "Staff Only?" msgstr "¿Solo personal de soporte?" -#: models.py:1219 +#: models.py:1264 msgid "" "If this is ticked, then the public submission form will NOT show this field" msgstr "Si está prendido, la forma pública de creación de ticket NO MOSTRARÁ este campo" -#: models.py:1262 +#: models.py:1273 +msgid "Custom field" +msgstr "" + +#: models.py:1274 +msgid "Custom fields" +msgstr "" + +#: models.py:1297 +msgid "Ticket custom field value" +msgstr "" + +#: models.py:1298 +msgid "Ticket custom field values" +msgstr "" + +#: models.py:1315 msgid "Depends On Ticket" msgstr "Depende del ticket" -#: management/commands/create_usersettings.py:21 +#: models.py:1324 +msgid "Ticket dependency" +msgstr "" + +#: models.py:1325 +msgid "Ticket dependencies" +msgstr "" + +#: management/commands/create_usersettings.py:25 msgid "" "Check for user without django-helpdesk UserSettings and create settings if " "required. Uses settings.DEFAULT_USER_SETTINGS which can be overridden to " "suit your situation." msgstr "Busca al usuario sin django-helpdesk UserSettings y crea los UserSettings si es necesario. Utiliza settings.DEFAULT_USER_SETTINGS , que puede ser sobreescrito para su situación particular." -#: management/commands/escalate_tickets.py:143 +#: management/commands/escalate_tickets.py:148 #, python-format msgid "Ticket escalated after %s days" msgstr "Ticket escalado después de %s días" -#: management/commands/get_email.py:151 +#: management/commands/get_email.py:158 msgid "Created from e-mail" msgstr "Creado a partir de e-mail" -#: management/commands/get_email.py:155 +#: management/commands/get_email.py:162 msgid "Unknown Sender" msgstr "Remitente desconocido" -#: management/commands/get_email.py:209 +#: management/commands/get_email.py:216 msgid "" "No plain-text email body available. Please see attachment " "email_html_body.html." msgstr "No hay cuerpo del correo electrónico en texto plano disponible. Por favor, consulte el archivo adjunto email_html_body.html." -#: management/commands/get_email.py:213 +#: management/commands/get_email.py:220 msgid "email_html_body.html" msgstr "email_html_body.html" -#: management/commands/get_email.py:256 +#: management/commands/get_email.py:263 #, python-format msgid "E-Mail Received from %(sender_email)s" msgstr "E-mail recibido desde %(sender_email)s " -#: management/commands/get_email.py:264 +#: management/commands/get_email.py:271 #, python-format msgid "Ticket Re-Opened by E-Mail Received from %(sender_email)s" msgstr "Ticket Re-abierto por el correo electrónico recibido desde %(sender_email)s " -#: management/commands/get_email.py:322 +#: management/commands/get_email.py:329 msgid " (Reopened)" msgstr "(Reabierto)" -#: management/commands/get_email.py:324 +#: management/commands/get_email.py:331 msgid " (Updated)" msgstr "(Actualizado)" #: templates/helpdesk/attribution.html:2 msgid "" -"Powered by django-" -"helpdesk." -msgstr "Desarrollado por django-helpdesk." +"django-helpdesk." +msgstr "" -#: templates/helpdesk/attribution.html:4 -msgid "For technical support please contact:" -msgstr "Para soporte técnico por favor comuniquese con:" - -#: templates/helpdesk/base.html:9 +#: templates/helpdesk/base.html:10 msgid "Powered by django-helpdesk" msgstr "Desarrollado por django-helpdesk" -#: templates/helpdesk/base.html:19 templates/helpdesk/rss_list.html:9 -#: templates/helpdesk/rss_list.html:23 templates/helpdesk/rss_list.html:28 +#: templates/helpdesk/base.html:20 templates/helpdesk/rss_list.html:9 +#: templates/helpdesk/rss_list.html:24 templates/helpdesk/rss_list.html:31 msgid "My Open Tickets" msgstr "Mis Tickets Abiertos" -#: templates/helpdesk/base.html:20 +#: templates/helpdesk/base.html:21 msgid "All Recent Activity" msgstr "Todas las actividades recientes" -#: templates/helpdesk/base.html:21 templates/helpdesk/dashboard.html:76 +#: templates/helpdesk/base.html:22 templates/helpdesk/dashboard.html:99 #: templates/helpdesk/rss_list.html:15 msgid "Unassigned Tickets" msgstr "Tickets sin asignar" -#: templates/helpdesk/base.html:101 templates/helpdesk/public_base.html:6 -#: templates/helpdesk/public_base.html:14 +#: templates/helpdesk/base.html:52 templates/helpdesk/public_base.html:6 +#: templates/helpdesk/public_base.html:18 msgid "Helpdesk" msgstr "Helpdesk" -#: templates/helpdesk/base.html:111 templates/helpdesk/rss_list.html:9 +#: templates/helpdesk/base.html:62 templates/helpdesk/rss_list.html:9 #: templates/helpdesk/rss_list.html:12 templates/helpdesk/rss_list.html:15 -#: templates/helpdesk/rss_list.html:27 templates/helpdesk/rss_list.html:28 +#: templates/helpdesk/rss_list.html:30 templates/helpdesk/rss_list.html:31 msgid "RSS Icon" msgstr "Icono Rss" -#: templates/helpdesk/base.html:111 templates/helpdesk/rss_list.html:2 +#: templates/helpdesk/base.html:62 templates/helpdesk/rss_list.html:2 #: templates/helpdesk/rss_list.html.py:4 msgid "RSS Feeds" msgstr "Fuente RSS" -#: templates/helpdesk/base.html:112 +#: templates/helpdesk/base.html:63 msgid "API" msgstr "API" -#: templates/helpdesk/base.html:113 -msgid "User Settings" -msgstr "Configuracion del Usuario" - -#: templates/helpdesk/base.html:115 -msgid "Change Language" -msgstr "Cambiar Idioma" - -#: templates/helpdesk/base.html:117 +#: templates/helpdesk/base.html:64 templates/helpdesk/system_settings.html:6 msgid "System Settings" msgstr "Configuración del Sistema" #: templates/helpdesk/confirm_delete_saved_query.html:3 -#: templates/helpdesk/ticket_list.html:144 +#: templates/helpdesk/ticket_list.html:146 msgid "Delete Saved Query" msgstr "Borrar Búsqueda Salvada" -#: templates/helpdesk/confirm_delete_saved_query.html:5 +#: templates/helpdesk/confirm_delete_saved_query.html:6 +msgid "Delete Query" +msgstr "" + +#: templates/helpdesk/confirm_delete_saved_query.html:8 #, python-format msgid "" -"\n" -"

Delete Query

\n" -"\n" -"

Are you sure you want to delete this saved filter (%(query_title)s)? To re-create it, you will need to manually re-filter your ticket listing.

\n" -msgstr "\n

Eliminar Consulta

\n\n

¿Esta seguro de eliminar el filtro guardado (%(query_title)s)? Para recrearlo, necesita volver a filtrar manualmente su lista de tickets.

\n" +"Are you sure you want to delete this saved filter " +"(%(query_title)s)? To re-create it, you will need to manually re-" +"filter your ticket listing." +msgstr "" #: templates/helpdesk/confirm_delete_saved_query.html:11 -msgid "You have shared this query, so other users may be using it. If you delete it, they will have to manually create their own query." -msgstr "Has compartido esta consulta, entonces otros usuarios podrían estar usandola, si tu la eliminas ellos tienen que crear manualmente su propia consulta" +msgid "" +"You have shared this query, so other users may be using it. If you delete " +"it, they will have to manually create their own query." +msgstr "" -#: templates/helpdesk/confirm_delete_saved_query.html:15 -#: templates/helpdesk/delete_ticket.html:11 +#: templates/helpdesk/confirm_delete_saved_query.html:14 +#: templates/helpdesk/delete_ticket.html:10 msgid "No, Don't Delete It" msgstr "No, No borrarlo" -#: templates/helpdesk/confirm_delete_saved_query.html:17 -#: templates/helpdesk/delete_ticket.html:13 +#: templates/helpdesk/confirm_delete_saved_query.html:16 +#: templates/helpdesk/delete_ticket.html:12 msgid "Yes - Delete It" msgstr "Sí, borrarlo" @@ -1072,26 +1174,24 @@ msgid "Create Ticket" msgstr "Crear Ticket" #: templates/helpdesk/create_ticket.html:10 -#: templates/helpdesk/public_homepage.html:39 +#: templates/helpdesk/navigation.html:65 templates/helpdesk/navigation.html:68 +#: templates/helpdesk/public_homepage.html:27 msgid "Submit a Ticket" msgstr "Enviar un Ticket" #: templates/helpdesk/create_ticket.html:11 +#: templates/helpdesk/edit_ticket.html:11 msgid "Unless otherwise stated, all fields are required." -msgstr "A menos que se indique lo contrario, todos los campos son obligatorios." +msgstr "" #: templates/helpdesk/create_ticket.html:11 +#: templates/helpdesk/edit_ticket.html:11 +#: templates/helpdesk/public_homepage.html:28 msgid "Please provide as descriptive a title and description as possible." -msgstr "Por favor use un título y descripción lo más claro posible." +msgstr "" -#: templates/helpdesk/create_ticket.html:17 -#: templates/helpdesk/edit_ticket.html:19 -#: templates/helpdesk/public_homepage.html:50 -msgid "(Optional)" -msgstr "(Opcional)" - -#: templates/helpdesk/create_ticket.html:26 -#: templates/helpdesk/public_homepage.html:59 +#: templates/helpdesk/create_ticket.html:30 +#: templates/helpdesk/public_homepage.html:55 msgid "Submit Ticket" msgstr "Enviar Ticket" @@ -1099,131 +1199,176 @@ msgstr "Enviar Ticket" msgid "Helpdesk Dashboard" msgstr "Panel - Servicio de Ayuda" -#: templates/helpdesk/dashboard.html:10 -msgid "Helpdesk Summary" -msgstr "Resumen - Servicio de Ayuda" - -#: templates/helpdesk/dashboard.html:25 +#: templates/helpdesk/dashboard.html:9 msgid "" "Welcome to your Helpdesk Dashboard! From here you can quickly see tickets " "submitted by you, tickets you are working on, and those tickets that have no" " owner." msgstr "Bienvenido al panel del servicio de ayuda, aquí podrá ver de inmediato sus tickets enviados, en cuales estas trabajando y los que no tienen dueño." -#: templates/helpdesk/dashboard.html:27 -msgid "" -"Welcome to your Helpdesk Dashboard! From here you can quickly see your own " -"tickets, and those tickets that have no owner. Why not pick up an orphan " -"ticket and sort it out for a customer?" -msgstr "Bienvenido al panel del servicio de ayuda, aquí podrá ver de inmediato sus tickets y los que no tienen dueño. ¿Porque no tomas un ticket y le das el seguimiento al cliente?" +#: templates/helpdesk/dashboard.html:14 +msgid "Helpdesk Summary" +msgstr "Resumen - Servicio de Ayuda" #: templates/helpdesk/dashboard.html:36 +msgid "Current Ticket Stats" +msgstr "" + +#: templates/helpdesk/dashboard.html:37 +msgid "Average number of days until ticket is closed (all tickets): " +msgstr "" + +#: templates/helpdesk/dashboard.html:38 +msgid "" +"Average number of days until ticket is closed (tickets opened in last 60 " +"days): " +msgstr "" + +#: templates/helpdesk/dashboard.html:39 +msgid "Click" +msgstr "" + +#: templates/helpdesk/dashboard.html:39 +msgid "for detailed average by month." +msgstr "" + +#: templates/helpdesk/dashboard.html:40 +msgid "Distribution of open tickets, grouped by time period:" +msgstr "" + +#: templates/helpdesk/dashboard.html:41 +msgid "Days since opened" +msgstr "" + +#: templates/helpdesk/dashboard.html:41 +msgid "Number of open tickets" +msgstr "" + +#: templates/helpdesk/dashboard.html:57 msgid "All Tickets submitted by you" msgstr "Todos los Tickets enviados por usted" -#: templates/helpdesk/dashboard.html:37 templates/helpdesk/dashboard.html:57 -#: templates/helpdesk/dashboard.html:77 templates/helpdesk/dashboard.html:99 -#: templates/helpdesk/ticket_list.html:199 +#: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 +#: templates/helpdesk/dashboard.html:100 templates/helpdesk/dashboard.html:124 +#: templates/helpdesk/ticket_list.html:225 msgid "Pr" msgstr "Pr" -#: templates/helpdesk/dashboard.html:37 templates/helpdesk/dashboard.html:57 -#: templates/helpdesk/dashboard.html:99 +#: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 +#: templates/helpdesk/dashboard.html:124 msgid "Last Update" msgstr "Última actualización" -#: templates/helpdesk/dashboard.html:56 +#: templates/helpdesk/dashboard.html:77 msgid "Open Tickets assigned to you (you are working on this ticket)" msgstr "Tickets abiertos asignados a usted (usted esta trabajando en este ticket)" -#: templates/helpdesk/dashboard.html:69 +#: templates/helpdesk/dashboard.html:92 msgid "You have no tickets assigned to you." msgstr "Usted no tiene Tickets asignados" -#: templates/helpdesk/dashboard.html:76 +#: templates/helpdesk/dashboard.html:99 msgid "(pick up a ticket if you start to work on it)" msgstr "(asigna un ticket si estas trabajando en el)" -#: templates/helpdesk/dashboard.html:85 -#: templates/helpdesk/ticket_desc_table.html:22 +#: templates/helpdesk/dashboard.html:110 +#: templates/helpdesk/ticket_desc_table.html:38 msgid "Take" msgstr "Tomar" -#: templates/helpdesk/dashboard.html:85 +#: templates/helpdesk/dashboard.html:110 #: templates/helpdesk/email_ignore_list.html:13 #: templates/helpdesk/email_ignore_list.html:23 #: templates/helpdesk/ticket_cc_list.html:15 #: templates/helpdesk/ticket_cc_list.html:23 -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Delete" msgstr "Borrar" -#: templates/helpdesk/dashboard.html:89 +#: templates/helpdesk/dashboard.html:114 msgid "There are no unassigned tickets." msgstr "No existen tickets sin asignar" -#: templates/helpdesk/dashboard.html:98 +#: templates/helpdesk/dashboard.html:123 msgid "Closed & resolved Tickets you used to work on" msgstr "Tickets cerrados y resueltos en los que usted trabajó" #: templates/helpdesk/delete_ticket.html:3 +#: templates/helpdesk/delete_ticket.html:6 msgid "Delete Ticket" msgstr "Borrar Ticket" #: templates/helpdesk/delete_ticket.html:8 #, python-format -msgid "Are you sure you want to delete this ticket (%(ticket_title)s)? All traces of the ticket, including followups, attachments, and updates will be irreversibly removed." -msgstr "¿Está seguro que desea eliminar esta entrada (%(ticket_title)s)? Todos los rastros del ticket, incluyendo comentarios, archivos adjuntos y actualizaciones serán eliminados de forma irreversible." +msgid "" +"Are you sure you want to delete this ticket (%(ticket_title)s)? All" +" traces of the ticket, including followups, attachments, and updates will be" +" irreversibly removed." +msgstr "" #: templates/helpdesk/edit_ticket.html:3 msgid "Edit Ticket" msgstr "Editar Ticket" -#: templates/helpdesk/edit_ticket.html:6 +#: templates/helpdesk/edit_ticket.html:9 msgid "Edit a Ticket" -msgstr "Editar un Ticket" +msgstr "" -#: templates/helpdesk/edit_ticket.html:6 +#: templates/helpdesk/edit_ticket.html:13 msgid "Note" -msgstr "Nota" +msgstr "" -#: templates/helpdesk/edit_ticket.html:6 -msgid "Editing a ticket does not send an e-mail to the ticket owner or submitter. No new details should be entered, this form should only be used to fix incorrect details or clean up the submission." -msgstr "La edición de un ticket no envía un correo electrónico al propietario del ticket o remitente. Este formato no es para añadir nuevos datos, sólo se debe utilizar para arreglar datos incorrectos o limpiar el ticket." +#: templates/helpdesk/edit_ticket.html:13 +msgid "" +"Editing a ticket does not send an e-mail to the ticket owner or " +"submitter. No new details should be entered, this form should only be used " +"to fix incorrect details or clean up the submission." +msgstr "" -#: templates/helpdesk/edit_ticket.html:28 +#: templates/helpdesk/edit_ticket.html:33 msgid "Save Changes" msgstr "Salvar Cambios" #: templates/helpdesk/email_ignore_add.html:3 +#: templates/helpdesk/email_ignore_add.html:6 #: templates/helpdesk/email_ignore_add.html:23 msgid "Ignore E-Mail Address" msgstr "Ignorar Dirección de E-mail" -#: templates/helpdesk/email_ignore_add.html:5 -msgid "To ignore an e-mail address and prevent any emails from that address creating tickets automatically, enter the e-mail address below." -msgstr "Para ignorar una dirección e-mail y evitar que se creen tickets automáticos desde la misma, introduzca la dirección de e-mail abajo." +#: templates/helpdesk/email_ignore_add.html:8 +msgid "" +"To ignore an e-mail address and prevent any emails from that address " +"creating tickets automatically, enter the e-mail address below." +msgstr "" -msgid "You can either enter a whole e-mail address such as email@domain.com or a portion of an e-mail address with a wildcard, such as *@domain.com or user@*." -msgstr "Puede especificar tanto una dirección de correo completo, por ejemplo email@dominio.com o solo una parte de la dirección con un wildcard, como por ejemplo *@dominio.com o usuario@*." +#: templates/helpdesk/email_ignore_add.html:10 +msgid "" +"You can either enter a whole e-mail address such as " +"email@domain.com or a portion of an e-mail address with a wildcard," +" such as *@domain.com or user@*." +msgstr "" #: templates/helpdesk/email_ignore_del.html:3 msgid "Delete Ignored E-Mail Address" msgstr "Borrar dirección de E-Mail Ignorada" -#: templates/helpdesk/email_ignore_del.html:5 +#: templates/helpdesk/email_ignore_del.html:6 msgid "Un-Ignore E-Mail Address" -msgstr "Readmitir dirección E-Mail" +msgstr "" +#: templates/helpdesk/email_ignore_del.html:8 #, python-format -msgid "Are you sure you wish to stop removing this email address (%(email_address)s) and allow their e-mails to automatically create tickets in your system? You can re-add this e-mail address at any time." -msgstr "¿Está seguro de que quiere dejar de bloquear esta dirección de correo (%(email_address)s) y permitir que los correos de esta dirección creen tickets en el sistema? Puede añadir esta dirección e-mail en cualquier momento." +msgid "" +"Are you sure you wish to stop removing this email address " +"(%(email_address)s) and allow their e-mails to automatically create" +" tickets in your system? You can re-add this e-mail address at any time." +msgstr "" -#: templates/helpdesk/email_ignore_del.html:11 +#: templates/helpdesk/email_ignore_del.html:10 msgid "Keep Ignoring It" msgstr "Mantener bloqueado" -#: templates/helpdesk/email_ignore_del.html:13 +#: templates/helpdesk/email_ignore_del.html:12 msgid "Stop Ignoring It" msgstr "Desbloquearlo" @@ -1244,16 +1389,12 @@ msgstr "" msgid "Date Added" msgstr "Fecha en que se añadió" -#: templates/helpdesk/email_ignore_list.html:13 -msgid "Queues" -msgstr "Departamentos" - #: templates/helpdesk/email_ignore_list.html:13 msgid "Keep in mailbox?" msgstr "Mantener en el mailbox?" #: templates/helpdesk/email_ignore_list.html:21 -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "All" msgstr "Todos" @@ -1288,7 +1429,7 @@ msgid "Comment:" msgstr "Comentario:" #: templates/helpdesk/kb_category.html:4 -#: templates/helpdesk/kb_category.html:11 +#: templates/helpdesk/kb_category.html:12 #, python-format msgid "Knowledgebase Category: %(kbcat)s" msgstr "Categoría del knowledgebase: %(kbcat)s " @@ -1298,12 +1439,12 @@ msgstr "Categoría del knowledgebase: %(kbcat)s " msgid "You are viewing all items in the %(kbcat)s category." msgstr "Usted está viendo todos los elementos de la categoría %(kbcat)s" -#: templates/helpdesk/kb_category.html:12 +#: templates/helpdesk/kb_category.html:13 msgid "Article" msgstr "Artículo" -#: templates/helpdesk/kb_index.html:4 templates/helpdesk/navigation.html:11 -#: templates/helpdesk/navigation.html:33 +#: templates/helpdesk/kb_index.html:4 templates/helpdesk/navigation.html:21 +#: templates/helpdesk/navigation.html:71 msgid "Knowledgebase" msgstr "Base de conocimientos" @@ -1314,8 +1455,8 @@ msgid "" "your problem prior to opening a support ticket." msgstr "" -#: templates/helpdesk/kb_index.html:9 -#: templates/helpdesk/public_homepage.html:9 +#: templates/helpdesk/kb_index.html:10 +#: templates/helpdesk/public_homepage.html:10 msgid "Knowledgebase Categories" msgstr "Categorías de la base de conocimientos" @@ -1324,7 +1465,7 @@ msgstr "Categorías de la base de conocimientos" msgid "Knowledgebase: %(item)s" msgstr "Base de Conocimientos: %(item)s" -#: templates/helpdesk/kb_item.html:13 +#: templates/helpdesk/kb_item.html:16 #, python-format msgid "" "View other %(category_title)s " @@ -1332,88 +1473,82 @@ msgid "" "articles." msgstr "" -#: templates/helpdesk/kb_item.html:15 +#: templates/helpdesk/kb_item.html:18 msgid "Feedback" msgstr "Retroalimentación" -#: templates/helpdesk/kb_item.html:17 +#: templates/helpdesk/kb_item.html:20 msgid "" "We give our users an opportunity to vote for items that they believe have " "helped them out, in order for us to better serve future customers. We would " "appreciate your feedback on this article. Did you find it useful?" msgstr "Damos a nuestros usuarios la oportunidad de votar sobre los artículos que ellos creen que les han ayudado, para que podamos servir mejor a los futuros clientes. Agradeceremos sus comentarios sobre este artículo. ¿Te ha resultado útil?" -#: templates/helpdesk/kb_item.html:20 +#: templates/helpdesk/kb_item.html:23 msgid "This article was useful to me" msgstr "Este artículo fue útil para mí" -#: templates/helpdesk/kb_item.html:21 +#: templates/helpdesk/kb_item.html:24 msgid "This article was not useful to me" msgstr "Este artículo no fue útil para mí" -#: templates/helpdesk/kb_item.html:24 +#: templates/helpdesk/kb_item.html:27 msgid "The results of voting by other readers of this article are below:" msgstr "Los resultados de la votación por otros lectores de este artículo se muestran a continuación:" -#: templates/helpdesk/kb_item.html:27 +#: templates/helpdesk/kb_item.html:30 #, python-format msgid "Recommendations: %(recommendations)s" msgstr "Recomendaciones: %(recommendations)s" -#: templates/helpdesk/kb_item.html:28 +#: templates/helpdesk/kb_item.html:31 #, python-format msgid "Votes: %(votes)s" msgstr "Votos: %(votes)s" -#: templates/helpdesk/kb_item.html:29 +#: templates/helpdesk/kb_item.html:32 #, python-format msgid "Overall Rating: %(score)s" msgstr "Calificación: %(score)s " -#: templates/helpdesk/navigation.html:4 +#: templates/helpdesk/navigation.html:16 templates/helpdesk/navigation.html:64 msgid "Dashboard" msgstr "Panel" -#: templates/helpdesk/navigation.html:5 -#: templates/helpdesk/ticket_list.html:198 -msgid "Tickets" -msgstr "Tickets" - -#: templates/helpdesk/navigation.html:6 +#: templates/helpdesk/navigation.html:18 msgid "New Ticket" msgstr "Nuevo Ticket" -#: templates/helpdesk/navigation.html:8 +#: templates/helpdesk/navigation.html:19 msgid "Stats" msgstr "Estadisticas" -#: templates/helpdesk/navigation.html:14 -#: templates/helpdesk/ticket_list.html:46 -msgid "Load Saved Query" -msgstr "Cargar Busqueda Salvada" +#: templates/helpdesk/navigation.html:24 +msgid "Saved Query" +msgstr "" -#: templates/helpdesk/navigation.html:25 templates/helpdesk/navigation.html:35 -msgid "Logout" -msgstr "Salir" +#: templates/helpdesk/navigation.html:39 +msgid "Change password" +msgstr "" -#: templates/helpdesk/navigation.html:26 +#: templates/helpdesk/navigation.html:50 msgid "Search..." msgstr "Buscar..." -#: templates/helpdesk/navigation.html:26 +#: templates/helpdesk/navigation.html:50 msgid "Enter a keyword, or a ticket number to jump straight to that ticket." msgstr "Escriba una palabra, o un número de ticket para ir a él" -#: templates/helpdesk/navigation.html:31 -msgid "Submit A Ticket" -msgstr "Enviar un Ticket" +#: templates/helpdesk/navigation.html:73 +msgid "Logout" +msgstr "Salir" -#: templates/helpdesk/navigation.html:35 +#: templates/helpdesk/navigation.html:73 msgid "Log In" msgstr "Entrar" #: templates/helpdesk/public_change_language.html:2 -#: templates/helpdesk/public_homepage.html:21 +#: templates/helpdesk/public_homepage.html:73 #: templates/helpdesk/public_view_form.html:4 #: templates/helpdesk/public_view_ticket.html:2 msgid "View a Ticket" @@ -1427,69 +1562,81 @@ msgstr "Cambiar el lenguaje mostrado" msgid "Knowledgebase Articles" msgstr "Artículos de la Base de Conocimientos" -#: templates/helpdesk/public_homepage.html:29 +#: templates/helpdesk/public_homepage.html:28 +msgid "All fields are required." +msgstr "" + +#: templates/helpdesk/public_homepage.html:66 +msgid "Please use button at upper right to login first." +msgstr "Por favor use el botón de la sección superior derecha para logearse primero." + +#: templates/helpdesk/public_homepage.html:82 #: templates/helpdesk/public_view_form.html:15 msgid "Your E-mail Address" msgstr "Su dirección de correo electrénico" -#: templates/helpdesk/public_homepage.html:33 +#: templates/helpdesk/public_homepage.html:86 #: templates/helpdesk/public_view_form.html:19 msgid "View Ticket" msgstr "Ver Ticket" -#: templates/helpdesk/public_homepage.html:41 -msgid "All fields are required." -msgstr "Todos los campos son requeridos." - -#: templates/helpdesk/public_homepage.html:67 -msgid "Please use button at upper right to login first." -msgstr "Por favor use el botón de la sección superior derecha para logearse primero." - #: templates/helpdesk/public_spam.html:4 msgid "Unable To Open Ticket" msgstr "No es posible abrir el Ticket" -#: templates/helpdesk/public_spam.html:6 +#: templates/helpdesk/public_spam.html:5 msgid "Sorry, but there has been an error trying to submit your ticket." -msgstr "Lo sentimos, pero se generó un error al tratar de ingresar su ticket." +msgstr "" -msgid "Our system has marked your submission as spam, so we are unable to save it. If this is not spam, please press back and re-type your message. Be careful to avoid sounding 'spammy', and if you have heaps of links please try removing them if possible." -msgstr "Nuestro sistema ha catalogado su envío como spam, por lo que no podemos guardarlo. Si no es spam, por favor presione atrás y reingrese su mensaje. Intente no ingresar palabras que puedan sonar a spam, y si tiene ligas en su mensaje trate de eliminarlas si es posible." +#: templates/helpdesk/public_spam.html:6 +msgid "" +"Our system has marked your submission as spam, so we are " +"unable to save it. If this is not spam, please press back and re-type your " +"message. Be careful to avoid sounding 'spammy', and if you have heaps of " +"links please try removing them if possible." +msgstr "" -msgid "We are sorry for any inconvenience, however this check is required to avoid our helpdesk resources being overloaded by spammers." -msgstr "Sentimos el inconveniente, pero necesitamos verificar el correo contra spam para evitar que nuestros recursos de helpdesk sean bloqueados por spammers." +#: templates/helpdesk/public_spam.html:7 +msgid "" +"We are sorry for any inconvenience, however this check is required to avoid " +"our helpdesk resources being overloaded by spammers." +msgstr "" #: templates/helpdesk/public_view_form.html:8 msgid "Error:" msgstr "Error:" -#: templates/helpdesk/public_view_ticket.html:8 +#: templates/helpdesk/public_view_ticket.html:9 #, python-format msgid "Queue: %(queue_name)s" msgstr "Fila: %(queue_name)s" -#: templates/helpdesk/public_view_ticket.html:11 -#: templates/helpdesk/ticket_desc_table.html:16 +#: templates/helpdesk/public_view_ticket.html:13 +#: templates/helpdesk/ticket_desc_table.html:32 msgid "Submitted On" msgstr "Enviado el día:" -#: templates/helpdesk/public_view_ticket.html:46 -#: templates/helpdesk/ticket_desc_table.html:74 +#: templates/helpdesk/public_view_ticket.html:35 +msgid "Tags" +msgstr "Etiquetas" + +#: templates/helpdesk/public_view_ticket.html:48 +#: templates/helpdesk/ticket_desc_table.html:26 msgid "Accept" msgstr "Aceptar" -#: templates/helpdesk/public_view_ticket.html:46 -#: templates/helpdesk/ticket_desc_table.html:74 +#: templates/helpdesk/public_view_ticket.html:48 +#: templates/helpdesk/ticket_desc_table.html:26 msgid "Accept and Close" msgstr "Aceptar y cerrar" -#: templates/helpdesk/public_view_ticket.html:55 -#: templates/helpdesk/ticket.html:64 +#: templates/helpdesk/public_view_ticket.html:57 +#: templates/helpdesk/ticket.html:66 msgid "Follow-Ups" msgstr "Seguimientos" -#: templates/helpdesk/public_view_ticket.html:63 -#: templates/helpdesk/ticket.html:92 +#: templates/helpdesk/public_view_ticket.html:65 +#: templates/helpdesk/ticket.html:100 #, python-format msgid "Changed %(field)s from %(old_value)s to %(new_value)s." msgstr "El campo(s) %(field)s cambió de %(old_value)s a %(new_value)s." @@ -1532,6 +1679,10 @@ msgstr "por Mes" msgid "Reports By Queue" msgstr "Reportes por Fila" +#: templates/helpdesk/report_index.html:27 views/staff.py:1049 +msgid "Days until ticket closed by Month" +msgstr "" + #: templates/helpdesk/report_output.html:19 msgid "" "You can run this query on filtered data by using one of your saved queries." @@ -1589,15 +1740,15 @@ msgid "" "new tickets coming into that queue." msgstr "" -#: templates/helpdesk/rss_list.html:22 +#: templates/helpdesk/rss_list.html:23 msgid "Per-Queue Feeds" msgstr "Fuentes RSS por cola" -#: templates/helpdesk/rss_list.html:23 +#: templates/helpdesk/rss_list.html:24 msgid "All Open Tickets" msgstr "Todos los Tickets Abiertos" -#: templates/helpdesk/rss_list.html:27 +#: templates/helpdesk/rss_list.html:30 msgid "Open Tickets" msgstr "Tickets Abiertos" @@ -1605,12 +1756,8 @@ msgstr "Tickets Abiertos" msgid "Change System Settings" msgstr "Cambiar la Configuración del Sistema" -#: templates/helpdesk/system_settings.html:5 -msgid "" -"\n" -"

System Settings

\n" -"\n" -"

The following items can be maintained by you or other superusers:

" +#: templates/helpdesk/system_settings.html:8 +msgid "The following items can be maintained by you or other superusers:" msgstr "" #: templates/helpdesk/system_settings.html:11 @@ -1649,77 +1796,81 @@ msgstr "Ver detalles del ticket" msgid "Attach another File" msgstr "Adjuntar otro archivo" -#: templates/helpdesk/ticket.html:34 templates/helpdesk/ticket.html.py:197 +#: templates/helpdesk/ticket.html:34 templates/helpdesk/ticket.html.py:200 msgid "Add Another File" msgstr "Agregar otro archivo" -#: templates/helpdesk/ticket.html:71 templates/helpdesk/ticket.html.py:81 +#: templates/helpdesk/ticket.html:73 templates/helpdesk/ticket.html.py:86 msgid "Private" msgstr "Privado" -#: templates/helpdesk/ticket.html:111 +#: templates/helpdesk/ticket.html:119 msgid "Respond to this ticket" msgstr "Responder a este ticket" -#: templates/helpdesk/ticket.html:118 +#: templates/helpdesk/ticket.html:126 msgid "Use a Pre-set Reply" msgstr "Use una plantilla de respuesta" -#: templates/helpdesk/ticket.html:120 +#: templates/helpdesk/ticket.html:126 templates/helpdesk/ticket.html.py:166 +msgid "(Optional)" +msgstr "(Opcional)" + +#: templates/helpdesk/ticket.html:128 msgid "" "Selecting a pre-set reply will over-write your comment below. You can then " "modify the pre-set reply to your liking before saving this update." msgstr "" -#: templates/helpdesk/ticket.html:123 +#: templates/helpdesk/ticket.html:131 msgid "Comment / Resolution" msgstr "Comentario / Resolución" -#: templates/helpdesk/ticket.html:125 +#: templates/helpdesk/ticket.html:133 msgid "" "You can insert ticket and queue details in your message. For more " "information, see the context help page." msgstr "" -#: templates/helpdesk/ticket.html:128 +#: templates/helpdesk/ticket.html:136 msgid "" "This ticket cannot be resolved or closed until the tickets it depends on are" " resolved." msgstr "" -#: templates/helpdesk/ticket.html:158 +#: templates/helpdesk/ticket.html:166 msgid "Is this update public?" msgstr "¿Esta actualización es pública?" -#: templates/helpdesk/ticket.html:160 +#: templates/helpdesk/ticket.html:168 msgid "" "If this is public, the submitter will be e-mailed your comment or " "resolution." msgstr "" -#: templates/helpdesk/ticket.html:164 +#: templates/helpdesk/ticket.html:172 msgid "Change Further Details »" msgstr "" -#: templates/helpdesk/ticket.html:173 templates/helpdesk/ticket_list.html:55 -#: templates/helpdesk/ticket_list.html:87 -#: templates/helpdesk/ticket_list.html:199 +#: templates/helpdesk/ticket.html:181 templates/helpdesk/ticket_list.html:68 +#: templates/helpdesk/ticket_list.html:97 +#: templates/helpdesk/ticket_list.html:225 msgid "Owner" msgstr "Dueño" -#: templates/helpdesk/ticket.html:174 +#: templates/helpdesk/ticket.html:182 msgid "Unassign" msgstr "" -#: templates/helpdesk/ticket.html:190 +#: templates/helpdesk/ticket.html:193 msgid "Attach File(s) »" msgstr "" -#: templates/helpdesk/ticket.html:196 +#: templates/helpdesk/ticket.html:199 msgid "Attach a File" msgstr "Adjuntar archivo" -#: templates/helpdesk/ticket.html:204 +#: templates/helpdesk/ticket.html:207 msgid "Update This Ticket" msgstr "Actualizar este Ticket" @@ -1822,263 +1973,256 @@ msgid "" "

Are you sure you wish to remove the dependency on this ticket?

\n" msgstr "" -#: templates/helpdesk/ticket_desc_table.html:11 +#: templates/helpdesk/ticket_desc_table.html:7 msgid "Unhold" msgstr "" -#: templates/helpdesk/ticket_desc_table.html:11 +#: templates/helpdesk/ticket_desc_table.html:7 msgid "Hold" msgstr "" -#: templates/helpdesk/ticket_desc_table.html:13 +#: templates/helpdesk/ticket_desc_table.html:9 #, python-format msgid "Queue: %(queue)s" msgstr "Departamento: %(queue)s" -#: templates/helpdesk/ticket_desc_table.html:21 +#: templates/helpdesk/ticket_desc_table.html:37 msgid "Assigned To" msgstr "Asignado A " -#: templates/helpdesk/ticket_desc_table.html:27 +#: templates/helpdesk/ticket_desc_table.html:43 msgid "Ignore" msgstr "Ignorar" -#: templates/helpdesk/ticket_desc_table.html:36 +#: templates/helpdesk/ticket_desc_table.html:52 msgid "Copies To" msgstr "Copia a" -#: templates/helpdesk/ticket_desc_table.html:37 +#: templates/helpdesk/ticket_desc_table.html:53 msgid "Manage" msgstr "Administrar" -#: templates/helpdesk/ticket_desc_table.html:37 +#: templates/helpdesk/ticket_desc_table.html:53 msgid "" "Click here to add / remove people who should receive an e-mail whenever this" " ticket is updated." msgstr "" -#: templates/helpdesk/ticket_desc_table.html:48 +#: templates/helpdesk/ticket_desc_table.html:53 +msgid "Subscribe" +msgstr "" + +#: templates/helpdesk/ticket_desc_table.html:53 +msgid "" +"Click here to subscribe yourself to this ticket, if you want to receive an " +"e-mail whenever this ticket is updated." +msgstr "" + +#: templates/helpdesk/ticket_desc_table.html:57 msgid "Dependencies" msgstr "Dependencias" -#: templates/helpdesk/ticket_desc_table.html:50 +#: templates/helpdesk/ticket_desc_table.html:59 msgid "" "This ticket cannot be resolved until the following ticket(s) are resolved" msgstr "Este ticket no se puede resolver hasta que el/los siguiente(s) tickets se resuelvan" -#: templates/helpdesk/ticket_desc_table.html:51 +#: templates/helpdesk/ticket_desc_table.html:60 msgid "Remove Dependency" msgstr "Remover Dependencia" -#: templates/helpdesk/ticket_desc_table.html:54 +#: templates/helpdesk/ticket_desc_table.html:63 msgid "This ticket has no dependencies." msgstr "Este Ticket no tiene dependencias" -#: templates/helpdesk/ticket_desc_table.html:56 +#: templates/helpdesk/ticket_desc_table.html:65 msgid "Add Dependency" msgstr "Añadir Dependencia" -#: templates/helpdesk/ticket_desc_table.html:56 +#: templates/helpdesk/ticket_desc_table.html:65 msgid "" "Click on 'Add Dependency', if you want to make this ticket dependent on " "another ticket. A ticket may not be closed until all tickets it depends on " "are closed." msgstr "" -#: templates/helpdesk/ticket_list.html:2 -msgid "Ticket Listing" -msgstr "Listado de Tickets" - -#: templates/helpdesk/ticket_list.html:41 -msgid "Query Options" -msgstr "Opciones de consulta" - -#: templates/helpdesk/ticket_list.html:43 -msgid "Save This Query" -msgstr "Guardar consulta" - -#: templates/helpdesk/ticket_list.html:51 +#: templates/helpdesk/ticket_list.html:59 msgid "Change Query" msgstr "Cambiar consulta" -#: templates/helpdesk/ticket_list.html:54 -#: templates/helpdesk/ticket_list.html:69 +#: templates/helpdesk/ticket_list.html:67 +#: templates/helpdesk/ticket_list.html:79 msgid "Sorting" msgstr "Ordenar" -#: templates/helpdesk/ticket_list.html:58 -#: templates/helpdesk/ticket_list.html:137 +#: templates/helpdesk/ticket_list.html:71 +#: templates/helpdesk/ticket_list.html:139 msgid "Keywords" msgstr "Palabras Clave" -#: templates/helpdesk/ticket_list.html:59 +#: templates/helpdesk/ticket_list.html:72 msgid "Date Range" msgstr "Rango de fechas" -#: templates/helpdesk/ticket_list.html:90 +#: templates/helpdesk/ticket_list.html:100 msgid "Reverse" msgstr "Inverso" -#: templates/helpdesk/ticket_list.html:92 +#: templates/helpdesk/ticket_list.html:102 msgid "Ordering applied to tickets" msgstr "Orden aplicado a los Tickets" -#: templates/helpdesk/ticket_list.html:97 +#: templates/helpdesk/ticket_list.html:107 msgid "Owner(s)" msgstr "Propietario(s)" -#: templates/helpdesk/ticket_list.html:101 +#: templates/helpdesk/ticket_list.html:111 msgid "(ME)" msgstr "(Yo)" -#: templates/helpdesk/ticket_list.html:105 +#: templates/helpdesk/ticket_list.html:115 msgid "Ctrl-Click to select multiple options" msgstr "Ctrl-Click para seleccionar múltiples opciones" -#: templates/helpdesk/ticket_list.html:110 +#: templates/helpdesk/ticket_list.html:120 msgid "Queue(s)" msgstr "Fila(s)" -#: templates/helpdesk/ticket_list.html:111 -#: templates/helpdesk/ticket_list.html:117 -#: templates/helpdesk/ticket_list.html:131 +#: templates/helpdesk/ticket_list.html:121 +#: templates/helpdesk/ticket_list.html:127 msgid "Ctrl-click to select multiple options" msgstr "Ctrl-Click para seleccionar múltiples opciones" -#: templates/helpdesk/ticket_list.html:116 +#: templates/helpdesk/ticket_list.html:126 msgid "Status(es)" msgstr "Estado(s)" -#: templates/helpdesk/ticket_list.html:122 +#: templates/helpdesk/ticket_list.html:132 msgid "Date (From)" msgstr "Fecha (de)" -#: templates/helpdesk/ticket_list.html:123 +#: templates/helpdesk/ticket_list.html:133 msgid "Date (To)" msgstr "Fecha (hasta)" -#: templates/helpdesk/ticket_list.html:124 +#: templates/helpdesk/ticket_list.html:134 msgid "Use YYYY-MM-DD date format, eg 2011-05-29" msgstr "Usar el formato de fechas YYYY-MM-DD, por ejemplo: 2011-05-29" -#: templates/helpdesk/ticket_list.html:130 -msgid "Tag(s)" -msgstr "Etiqueta(s)" - -#: templates/helpdesk/ticket_list.html:138 +#: templates/helpdesk/ticket_list.html:140 msgid "" "Keywords are case-insensitive, and will be looked for in the title, body and" " submitter fields." msgstr "" -#: templates/helpdesk/ticket_list.html:142 +#: templates/helpdesk/ticket_list.html:144 msgid "Apply Filter" msgstr "Aplicar Filtro" -#: templates/helpdesk/ticket_list.html:144 +#: templates/helpdesk/ticket_list.html:146 #, python-format -msgid "You are currently viewing saved query %(query_name)s." +msgid "You are currently viewing saved query \"%(query_name)s\"." msgstr "" -#: templates/helpdesk/ticket_list.html:147 +#: templates/helpdesk/ticket_list.html:149 #, python-format msgid "" "Run a report on this " "query to see stats and charts for the data listed below." msgstr "" -#: templates/helpdesk/ticket_list.html:154 -#: templates/helpdesk/ticket_list.html:169 +#: templates/helpdesk/ticket_list.html:162 +#: templates/helpdesk/ticket_list.html:181 msgid "Save Query" msgstr "Guardar consulta" -#: templates/helpdesk/ticket_list.html:160 +#: templates/helpdesk/ticket_list.html:172 msgid "" "This name appears in the drop-down list of saved queries. If you share your " "query, other users will see this name, so choose something clear and " "descriptive!" msgstr "" -#: templates/helpdesk/ticket_list.html:162 +#: templates/helpdesk/ticket_list.html:174 msgid "Shared?" msgstr "¿Compartido?" -#: templates/helpdesk/ticket_list.html:163 +#: templates/helpdesk/ticket_list.html:175 msgid "Yes, share this query with other users." msgstr "Si, compartir esta búsqueda con otros usuarios" -#: templates/helpdesk/ticket_list.html:164 +#: templates/helpdesk/ticket_list.html:176 msgid "" "If you share this query, it will be visible by all other logged-in " "users." msgstr "Si compartes esta búsqueda, esta será visible para todos los usuarios." -#: templates/helpdesk/ticket_list.html:176 +#: templates/helpdesk/ticket_list.html:195 msgid "Use Saved Query" msgstr "Usar consulta guardada" -#: templates/helpdesk/ticket_list.html:178 +#: templates/helpdesk/ticket_list.html:202 msgid "Query" msgstr "Consulta" -#: templates/helpdesk/ticket_list.html:183 +#: templates/helpdesk/ticket_list.html:207 msgid "Run Query" msgstr "Correr consulta" -#: templates/helpdesk/ticket_list.html:213 +#: templates/helpdesk/ticket_list.html:240 msgid "No Tickets Match Your Selection" msgstr "No coinciden tickets de acuerdo a su consulta" -#: templates/helpdesk/ticket_list.html:219 +#: templates/helpdesk/ticket_list.html:247 msgid "Previous" msgstr "Anterior" -#: templates/helpdesk/ticket_list.html:223 +#: templates/helpdesk/ticket_list.html:251 #, python-format msgid "Page %(ticket_num)s of %(num_pages)s." msgstr "Página%(ticket_num)s de %(num_pages)s." -#: templates/helpdesk/ticket_list.html:227 +#: templates/helpdesk/ticket_list.html:255 msgid "Next" msgstr "Siguiente" -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "Select:" msgstr "Seleccionar:" -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "None" msgstr "Ninguno" -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "Inverse" msgstr "Inverso" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "With Selected Tickets:" msgstr "Con los tickets seleccionados:" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Take (Assign to me)" msgstr "Tomar (Asignarmelo)" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Close" msgstr "Cerrar" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Close (Don't Send E-Mail)" msgstr "Cerrar (Sin enviar E-mail)" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Close (Send E-Mail)" msgstr "Cerrar (Enviar E-mail)" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Assign To" msgstr "Asignar A" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Nobody (Unassign)" msgstr "Nadie (Dejar de asignar)" @@ -2086,15 +2230,13 @@ msgstr "Nadie (Dejar de asignar)" msgid "Change User Settings" msgstr "Cambiar ajustes de usuario" -#: templates/helpdesk/user_settings.html:14 +#: templates/helpdesk/user_settings.html:8 msgid "" -"\n" -"

User Settings

\n" -"\n" -"

Use the following options to change the way your helpdesk system works for you. These settings do not impact any other user.

\n" +"Use the following options to change the way your helpdesk system works for " +"you. These settings do not impact any other user." msgstr "" -#: templates/helpdesk/user_settings.html:29 +#: templates/helpdesk/user_settings.html:14 msgid "Save Options" msgstr "Salvar opciones" @@ -2115,116 +2257,101 @@ msgstr "\n

Sesión cerrada

\n\n

Gracias por estar aquí. Esperamos que msgid "Helpdesk Login" msgstr "Ingresar a Helpdesk" -#: templates/helpdesk/registration/login.html:9 -#: templates/helpdesk/registration/login.html:21 -msgid "Login" -msgstr "Entrar" - -#: templates/helpdesk/registration/login.html:11 -msgid "" -"To log in and begin responding to cases, simply enter your username and " -"password below." -msgstr "Para entrar, simplemente introduzca su nombre de usuario y contraseña abajo." - #: templates/helpdesk/registration/login.html:14 +msgid "To log in simply enter your username and password below." +msgstr "" + +#: templates/helpdesk/registration/login.html:17 msgid "Your username and password didn't match. Please try again." msgstr "Su nombre de usuario y contraseña no coinciden, por favor intente otra vez." -#: templates/helpdesk/registration/login.html:16 -msgid "Username" -msgstr "Usuario" +#: templates/helpdesk/registration/login.html:20 +msgid "Login" +msgstr "Entrar" -#: templates/helpdesk/registration/login.html:18 -msgid "Password" -msgstr "Contraseña" - -#: views/feeds.py:35 +#: views/feeds.py:39 #, python-format msgid "Helpdesk: Open Tickets in queue %(queue)s for %(username)s" msgstr "Helpdesk: Abrir Tickets en cola %(queue)s for %(username)s" -#: views/feeds.py:40 +#: views/feeds.py:44 #, python-format msgid "Helpdesk: Open Tickets for %(username)s" msgstr "Helpdesk: Abrir Tickets para %(username)s" -#: views/feeds.py:46 +#: views/feeds.py:50 #, python-format msgid "Open and Reopened Tickets in queue %(queue)s for %(username)s" msgstr "Abrir y reabrir Tickets en %(queue)s para %(username)s" -#: views/feeds.py:51 +#: views/feeds.py:55 #, python-format msgid "Open and Reopened Tickets for %(username)s" msgstr "Abrir y reabrir Tickets para %(username)s" -#: views/feeds.py:98 +#: views/feeds.py:102 msgid "Helpdesk: Unassigned Tickets" msgstr "Helpdesk: Tickets no asignados" -#: views/feeds.py:99 +#: views/feeds.py:103 msgid "Unassigned Open and Reopened tickets" msgstr "Tickets no asignados abiertos y reabiertos" -#: views/feeds.py:124 +#: views/feeds.py:128 msgid "Helpdesk: Recent Followups" msgstr "Helpdesk: Actualizaciones recientes" -#: views/feeds.py:125 +#: views/feeds.py:129 msgid "" "Recent FollowUps, such as e-mail replies, comments, attachments and " "resolutions" msgstr "Actualizaciones recientes, como respuestas por e-mail, comentarios, adjuntos y resoluciones" -#: views/feeds.py:140 +#: views/feeds.py:144 #, python-format msgid "Helpdesk: Open Tickets in queue %(queue)s" msgstr "Helpdesk: Abrir Tickets en cola %(queue)s" -#: views/feeds.py:145 +#: views/feeds.py:149 #, python-format msgid "Open and Reopened Tickets in queue %(queue)s" msgstr "Abrir y reabrir tickets en cola %(queue)s" -#: views/public.py:91 +#: views/public.py:89 msgid "Invalid ticket ID or e-mail address. Please try again." msgstr "ID de ticket o dirección de e-mail inválido. Por favor intente nuevamente." -#: views/public.py:109 +#: views/public.py:107 msgid "Submitter accepted resolution and closed ticket" msgstr "El solicitante acepto la resolución y cerró el ticket." -#: views/staff.py:218 +#: views/staff.py:235 msgid "Accepted resolution and closed ticket" msgstr "Solución aceptada y ticket cerrado." -#: views/staff.py:246 -msgid "Sorry, you need to login to do that." -msgstr "Disculpe, usted necesita estar autenticado para hacer eso." - -#: views/staff.py:295 +#: views/staff.py:369 #, python-format msgid "Assigned to %(username)s" msgstr "Asignado a %(username)s" -#: views/staff.py:318 +#: views/staff.py:392 msgid "Updated" msgstr "Actualizado" -#: views/staff.py:496 +#: views/staff.py:577 #, python-format msgid "Assigned to %(username)s in bulk update" msgstr "Asignado a %(username)s en el paquete de actualizaciones" -#: views/staff.py:501 +#: views/staff.py:582 msgid "Unassigned in bulk update" msgstr "Sin asignar en el paquete de actualizaciones" -#: views/staff.py:506 views/staff.py:511 +#: views/staff.py:587 views/staff.py:592 msgid "Closed in bulk update" msgstr "Cerrado en el paquete de actualizaciones" -#: views/staff.py:732 +#: views/staff.py:806 msgid "" "

Note: Your keyword search is case sensitive because of " "your database. This means the search will not be accurate. " @@ -2234,86 +2361,38 @@ msgid "" "matching\">Django Documentation on string matching in SQLite." msgstr "

Nota: Su parámetro de busqueda es sensitivo producto de su base de datos. Esto significa que las búsquedas no serán precisas. Cambiando a una base de datos diferente, se lograrán mejores búsquedas. Para más información, revise Django Documentation on string matching in SQLite." -#: views/staff.py:843 +#: views/staff.py:910 msgid "Ticket taken off hold" msgstr "Ticket liberado" -#: views/staff.py:846 +#: views/staff.py:913 msgid "Ticket placed on hold" msgstr "Ticket puesto en espera" -#: views/staff.py:914 -msgid "Jan" -msgstr "Ene" - -#: views/staff.py:915 -msgid "Feb" -msgstr "Feb" - -#: views/staff.py:916 -msgid "Mar" -msgstr "Mar" - -#: views/staff.py:917 -msgid "Apr" -msgstr "Abr" - -#: views/staff.py:918 -msgid "May" -msgstr "May" - -#: views/staff.py:919 -msgid "Jun" -msgstr "Jun" - -#: views/staff.py:920 -msgid "Jul" -msgstr "Jul" - -#: views/staff.py:921 -msgid "Aug" -msgstr "Ago" - -#: views/staff.py:922 -msgid "Sep" -msgstr "Sep" - -#: views/staff.py:923 -msgid "Oct" -msgstr "Oct" - -#: views/staff.py:924 -msgid "Nov" -msgstr "Nov" - -#: views/staff.py:925 -msgid "Dec" -msgstr "Dic" - -#: views/staff.py:951 +#: views/staff.py:1007 msgid "User by Priority" msgstr "Usuario por Prioridad" -#: views/staff.py:957 +#: views/staff.py:1013 msgid "User by Queue" msgstr "Usuario por Cola" -#: views/staff.py:963 +#: views/staff.py:1019 msgid "User by Status" msgstr "Usuario por Estatus" -#: views/staff.py:969 +#: views/staff.py:1025 msgid "User by Month" msgstr "Usuario por Mes" -#: views/staff.py:975 +#: views/staff.py:1031 msgid "Queue by Priority" msgstr "Cola por Prioridad" -#: views/staff.py:981 +#: views/staff.py:1037 msgid "Queue by Status" msgstr "Cola por Estatus" -#: views/staff.py:987 +#: views/staff.py:1043 msgid "Queue by Month" msgstr "Cola por Mes" diff --git a/helpdesk/locale/fa_IR/LC_MESSAGES/django.mo b/helpdesk/locale/fa_IR/LC_MESSAGES/django.mo index 72bfa1f7..fa3c91fb 100644 Binary files a/helpdesk/locale/fa_IR/LC_MESSAGES/django.mo and b/helpdesk/locale/fa_IR/LC_MESSAGES/django.mo differ diff --git a/helpdesk/locale/fa_IR/LC_MESSAGES/django.po b/helpdesk/locale/fa_IR/LC_MESSAGES/django.po index ce15641b..a123fe17 100644 --- a/helpdesk/locale/fa_IR/LC_MESSAGES/django.po +++ b/helpdesk/locale/fa_IR/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # Translators: +# Morteza Nekoei , 2016 msgid "" msgstr "" "Project-Id-Version: django-helpdesk\n" "Report-Msgid-Bugs-To: http://github.com/RossP/django-helpdesk/issues\n" "POT-Creation-Date: 2014-07-26 14:14+0200\n" -"PO-Revision-Date: 2014-08-01 09:58+0000\n" -"Last-Translator: Ross Poulton \n" -"Language-Team: Persian (Iran) (http://www.transifex.com/projects/p/django-helpdesk/language/fa_IR/)\n" +"PO-Revision-Date: 2016-10-10 22:42+0000\n" +"Last-Translator: Morteza Nekoei \n" +"Language-Team: Persian (Iran) (http://www.transifex.com/rossp/django-helpdesk/language/fa_IR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -27,35 +28,35 @@ msgstr "" #: templates/helpdesk/ticket_list.html:225 views/staff.py:1032 #: views/staff.py:1038 views/staff.py:1044 views/staff.py:1050 msgid "Queue" -msgstr "" +msgstr "صف" #: forms.py:137 msgid "Summary of the problem" -msgstr "" +msgstr "خلاصه مشکل" #: forms.py:142 msgid "Submitter E-Mail Address" -msgstr "" +msgstr "آدرس ایمیل ثبت کننده" #: forms.py:144 msgid "" "This e-mail address will receive copies of all public updates to this " "ticket." -msgstr "" +msgstr "این آدرس ایمیل یک نسخه کپی از کلیه‌ی به‌روزرسانی‌های عمومی این تیکت را دریافت خواهد کرد." #: forms.py:150 msgid "Description of Issue" -msgstr "" +msgstr "توضیح این مسئله" #: forms.py:157 msgid "Case owner" -msgstr "" +msgstr "مالک" #: forms.py:158 msgid "" "If you select an owner other than yourself, they'll be e-mailed details of " "this ticket immediately." -msgstr "" +msgstr "اگر یک مالک غیر از خودتان را انتخاب نمایید، جزئیات این تیکت به صورت بلادرنگ برای آن‌ها ارسال خواهد شد" #: forms.py:166 models.py:327 management/commands/escalate_tickets.py:154 #: templates/helpdesk/public_view_ticket.html:23 @@ -63,28 +64,28 @@ msgstr "" #: templates/helpdesk/ticket_desc_table.html:47 #: templates/helpdesk/ticket_list.html:94 views/staff.py:429 msgid "Priority" -msgstr "" +msgstr "اولویت" #: forms.py:167 msgid "Please select a priority carefully. If unsure, leave it as '3'." -msgstr "" +msgstr "لطفا با دقت یک اولویت را انتخاب نمایید. در صورت عدم اطمینان، آن‌ را رها نمایید. (اولویت پیش‌فرض: ۳)" #: forms.py:174 forms.py:365 models.py:335 templates/helpdesk/ticket.html:186 #: views/staff.py:439 msgid "Due on" -msgstr "" +msgstr "در مدت زمان" #: forms.py:186 forms.py:370 msgid "Attach File" -msgstr "" +msgstr "ضمیمه کردن فایل" #: forms.py:187 forms.py:371 msgid "You can attach a file such as a document or screenshot to this ticket." -msgstr "" +msgstr "شما می‌توانید یک فایل مانند مستند یا عکس به این تیکت ضمیمه نمایید." #: forms.py:240 msgid "Ticket Opened" -msgstr "" +msgstr "تیکت باز است" #: forms.py:247 #, python-format @@ -93,68 +94,68 @@ msgstr "" #: forms.py:337 msgid "Summary of your query" -msgstr "" +msgstr "خلاصه پرس و جوی شما" #: forms.py:342 msgid "Your E-Mail Address" -msgstr "" +msgstr "آدرس ایمیل شما" #: forms.py:343 msgid "We will e-mail you when your ticket is updated." -msgstr "" +msgstr "زمانی‌ که تیکت به‌روزرسانی شود، برای شما ایمیلی ارسال خواهد شد." #: forms.py:348 msgid "Description of your issue" -msgstr "" +msgstr "توضیح مشکل شما" #: forms.py:350 msgid "" "Please be as descriptive as possible, including any details we may need to " "address your query." -msgstr "" +msgstr "لطفا تا جای امکان توضیحات لازم را وارد نمایید، توضیحاتی شامل هر نوع جزئیاتی که ما برای یافتن پرس و جوی شما لازم داریم." #: forms.py:358 msgid "Urgency" -msgstr "" +msgstr "اورژانسی" #: forms.py:359 msgid "Please select a priority carefully." -msgstr "" +msgstr "لطفا با دقت یک اولویت را انتخاب نمایید." #: forms.py:419 msgid "Ticket Opened Via Web" -msgstr "" +msgstr "تیکت از طریق وب باز شده است." #: forms.py:486 msgid "Show Ticket List on Login?" -msgstr "" +msgstr "لیست تیکت‌ها در زمان ورود نمایش داده شود؟" #: forms.py:487 msgid "Display the ticket list upon login? Otherwise, the dashboard is shown." -msgstr "" +msgstr "لیست تیکت‌ها در زمان ورود نمایش داده شود؟ در غیر اینصورت در داشبورد نمایش داده خواهند شد." #: forms.py:492 msgid "E-mail me on ticket change?" -msgstr "" +msgstr "تغییرات تیکت به من ایمیل شود؟" #: forms.py:493 msgid "" "If you're the ticket owner and the ticket is changed via the web by somebody" " else, do you want to receive an e-mail?" -msgstr "" +msgstr "اگر شما مالک تیکت هستید و تیکت از طریق وب توسط افراد دیگر تغییر یافت، آیا مایل هستید یک ایمیل اطلاع‌ رسانی دریافت نمایید؟" #: forms.py:498 msgid "E-mail me when assigned a ticket?" -msgstr "" +msgstr "زمانی‌که یک تیکت تخصیص یافت به من ایمیل ارسال شود؟" #: forms.py:499 msgid "" "If you are assigned a ticket via the web, do you want to receive an e-mail?" -msgstr "" +msgstr "اگر شما یک تیکت را از طریق وب تخصیص دادید، آیا مایل هستید یک ایمیل اطلاع‌رسانی دریافت نمایید؟" #: forms.py:504 msgid "E-mail me when a ticket is changed via the API?" -msgstr "" +msgstr "زمانی‌که یک تیکت از طریق API تغییر یافت، برای من ایمیل ارسال شود؟" #: forms.py:505 msgid "If a ticket is altered by the API, do you want to receive an e-mail?" @@ -162,22 +163,22 @@ msgstr "" #: forms.py:510 msgid "Number of tickets to show per page" -msgstr "" +msgstr "تعداد تیکت‌های قابل نمایش در هر صفحه" #: forms.py:511 msgid "How many tickets do you want to see on the Ticket List page?" -msgstr "" +msgstr "مایل هستید چه تعداد تیکت در صفحه‌ی لیست تیکت برای شما نمایش داده شود؟" #: forms.py:518 msgid "Use my e-mail address when submitting tickets?" -msgstr "" +msgstr "ایمیل آدرس من در زمان ثبت تیکت‌ها استفاده شود." #: forms.py:519 msgid "" "When you submit a ticket, do you want to automatically use your e-mail " "address as the submitter address? You can type a different e-mail address " "when entering the ticket if needed, this option only changes the default." -msgstr "" +msgstr "زمانی که یک تیکت ثبت نمودید، آیا مایل هستید به صورت خودکار آدرس ایمیل خود را به عنوان آدرس ایمیل ثبت کننده استفاده نمایید؟ شما میتوانید در صورت تمایل یک آدرس ایمیل دیگر زمان ثبت تیکت استفاده نمایید." #: models.py:35 models.py:261 models.py:503 models.py:817 models.py:853 #: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 @@ -185,7 +186,7 @@ msgstr "" #: templates/helpdesk/ticket.html:178 templates/helpdesk/ticket_list.html:85 #: templates/helpdesk/ticket_list.html:225 views/staff.py:419 msgid "Title" -msgstr "" +msgstr "عنوان" #: models.py:40 models.py:822 models.py:1206 msgid "Slug" @@ -201,39 +202,39 @@ msgstr "" #: templates/helpdesk/email_ignore_list.html:13 #: templates/helpdesk/ticket_cc_list.html:15 msgid "E-Mail Address" -msgstr "" +msgstr "آدرس ایمیل" #: models.py:49 msgid "" "All outgoing e-mails for this queue will use this e-mail address. If you use" " IMAP or POP3, this should be the e-mail address for that mailbox." -msgstr "" +msgstr "کلیه‌ی ایمیل‌های ارسالی برای این صف، از این ایمیل استفاده خواهند کرد. اگر می‌خواهید از IMAP یا POP3 استفاده کنید، آدرس ایمیل شما باید مرتبط با آن ایمیل سرور باشد." #: models.py:55 models.py:794 msgid "Locale" -msgstr "" +msgstr "موقعیت/محل" #: models.py:59 msgid "" "Locale of this queue. All correspondence in this queue will be in this " "language." -msgstr "" +msgstr "موقعیت این صف. کلیه‌ی پاسخ‌ها و تعاملات در این صف، با این زبان استفاده خواهد شد." #: models.py:63 msgid "Allow Public Submission?" -msgstr "" +msgstr "اجازه دادن ثبت‌های عمومی؟" #: models.py:66 msgid "Should this queue be listed on the public submission form?" -msgstr "" +msgstr "آیا این صف در فرم ثبت‌های عمومی لیست شود؟" #: models.py:71 msgid "Allow E-Mail Submission?" -msgstr "" +msgstr "اجازه‌ دادن ثبت ایمیل‌؟" #: models.py:74 msgid "Do you want to poll the e-mail box below for new tickets?" -msgstr "" +msgstr "آیا می‌خواهید ایمیل زیر را برای تیکت‌های جدید انتخاب نمایید؟" #: models.py:79 msgid "Escalation Days" @@ -243,22 +244,22 @@ msgstr "" msgid "" "For tickets which are not held, how often do you wish to increase their " "priority? Set to 0 for no escalation." -msgstr "" +msgstr "برای تیکت‌هایی که نگهداری نشده‌اند، آیا می‌خواهید اولویتی برای آن‌ها در نظر بگیرید؟ عدد ۰ را برای عدم استفاده از اولویت بکار برید." #: models.py:87 msgid "New Ticket CC Address" -msgstr "" +msgstr "یک آدرس کپی (CC) برای تیکت جدید" #: models.py:91 msgid "" "If an e-mail address is entered here, then it will receive notification of " "all new tickets created for this queue. Enter a comma between multiple " "e-mail addresses." -msgstr "" +msgstr "اگر یک آدرس ایمیل در این قسمت وارد شود، این آدرس کلیه‌ی تیکت‌های ایجاد شده برای این صف را دریافت خواهد نمود. جهت استفاده از بیش از یک آدرس ایمیل از کاما استفاده نمایید." #: models.py:97 msgid "Updated Ticket CC Address" -msgstr "" +msgstr "آدرس تیکت (CC) به‌روزرسانی شده" #: models.py:101 msgid "" diff --git a/helpdesk/locale/fr/LC_MESSAGES/django.mo b/helpdesk/locale/fr/LC_MESSAGES/django.mo index f2b70a2f..d950d467 100644 Binary files a/helpdesk/locale/fr/LC_MESSAGES/django.mo and b/helpdesk/locale/fr/LC_MESSAGES/django.mo differ diff --git a/helpdesk/locale/fr/LC_MESSAGES/django.po b/helpdesk/locale/fr/LC_MESSAGES/django.po index 8b4ef8bd..a28511da 100644 --- a/helpdesk/locale/fr/LC_MESSAGES/django.po +++ b/helpdesk/locale/fr/LC_MESSAGES/django.po @@ -6,18 +6,20 @@ # Translators: # Alexandre Papin , 2013 # Alex Garel , 2012 -# Antoine Nguyen , 2014 +# Antoine Nguyen , 2014,2016 +# Etienne Desgagné , 2015 # yaap , 2012 -# kolin22 , 2011 -# Ross Poulton , 2011 +# kolin22 , 2011 +# Paul Guichon , 2015 +# Ross Poulton , 2011,2015 msgid "" msgstr "" "Project-Id-Version: django-helpdesk\n" "Report-Msgid-Bugs-To: http://github.com/RossP/django-helpdesk/issues\n" "POT-Creation-Date: 2014-07-26 14:14+0200\n" -"PO-Revision-Date: 2014-09-17 07:12+0000\n" +"PO-Revision-Date: 2016-06-07 12:22+0000\n" "Last-Translator: Antoine Nguyen \n" -"Language-Team: French (http://www.transifex.com/projects/p/django-helpdesk/language/fr/)\n" +"Language-Team: French (http://www.transifex.com/rossp/django-helpdesk/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -497,7 +499,7 @@ msgstr " - En attente" #: models.py:394 msgid " - Open dependencies" -msgstr "" +msgstr "Dépendance ouverte" #: models.py:448 models.py:494 models.py:1117 models.py:1280 models.py:1309 #: templates/helpdesk/public_homepage.html:78 @@ -548,7 +550,7 @@ msgstr "Suivi" #: models.py:543 msgid "Follow-ups" -msgstr "" +msgstr "Suivis" #: models.py:570 models.py:1285 msgid "Field" @@ -578,11 +580,11 @@ msgstr "changé de \"%(old_value)s\" à \"%(new_value)s\"" #: models.py:600 msgid "Ticket change" -msgstr "" +msgstr "Changement de ticket" #: models.py:601 msgid "Ticket changes" -msgstr "" +msgstr "Changements de ticket" #: models.py:632 msgid "File" @@ -640,11 +642,11 @@ msgstr "Context disponible: {{ ticket }} - objet du ticket (eg {{ ticket.title } #: models.py:705 msgid "Pre-set reply" -msgstr "" +msgstr "Réponse préétablie" #: models.py:706 msgid "Pre-set replies" -msgstr "" +msgstr "Réponse préétablie" #: models.py:727 msgid "" @@ -658,11 +660,11 @@ msgstr "Jours exclus du processus d'augmentation des priorités" #: models.py:746 msgid "Escalation exclusion" -msgstr "" +msgstr "Exclusion priorités" #: models.py:747 msgid "Escalation exclusions" -msgstr "" +msgstr "Exclusion priorités" #: models.py:760 msgid "Template Name" @@ -713,19 +715,19 @@ msgstr "Langue de ce modèle." #: models.py:806 msgid "e-mail template" -msgstr "" +msgstr "Modèle d'e-mail" #: models.py:807 msgid "e-mail templates" -msgstr "" +msgstr "Modèles d'e-mail" #: models.py:834 msgid "Knowledge base category" -msgstr "" +msgstr "Catégorie de la base de connaissance" #: models.py:835 msgid "Knowledge base categories" -msgstr "" +msgstr "Catégories de la base de connaissance" #: models.py:849 templates/helpdesk/kb_index.html:11 #: templates/helpdesk/public_homepage.html:11 @@ -770,11 +772,11 @@ msgstr "Non évalué" #: models.py:901 msgid "Knowledge base item" -msgstr "" +msgstr "Élément de la base de connaissance" #: models.py:902 msgid "Knowledge base items" -msgstr "" +msgstr "Éléments de la base de connaissance" #: models.py:926 templates/helpdesk/ticket_list.html:170 msgid "Query Name" @@ -855,11 +857,11 @@ msgstr "Voulez-vous enregistrer les courriels provenant de cette adresse dans la #: models.py:1101 msgid "Ignored e-mail address" -msgstr "" +msgstr "Adresse e-mail ignorée" #: models.py:1102 msgid "Ignored e-mail addresses" -msgstr "" +msgstr "Adresses e-mail ignorées" #: models.py:1124 msgid "User who wishes to receive updates for this ticket." @@ -1024,11 +1026,11 @@ msgstr "Champs personnalisés" #: models.py:1297 msgid "Ticket custom field value" -msgstr "" +msgstr "Valeur champs personnalisé billet" #: models.py:1298 msgid "Ticket custom field values" -msgstr "" +msgstr "Valeur champs personnalisé billet" #: models.py:1315 msgid "Depends On Ticket" @@ -1036,11 +1038,11 @@ msgstr "Dépend du ticket" #: models.py:1324 msgid "Ticket dependency" -msgstr "" +msgstr "Dépendance du ticket" #: models.py:1325 msgid "Ticket dependencies" -msgstr "" +msgstr "Dépendances du ticket" #: management/commands/create_usersettings.py:25 msgid "" @@ -1093,7 +1095,7 @@ msgstr "(Mis à jour)" #: templates/helpdesk/attribution.html:2 msgid "" "django-helpdesk." -msgstr "" +msgstr "django-helpdesk." #: templates/helpdesk/base.html:10 msgid "Powered by django-helpdesk" @@ -1144,7 +1146,7 @@ msgstr "Supprimer la requête enregistrée" #: templates/helpdesk/confirm_delete_saved_query.html:6 msgid "Delete Query" -msgstr "" +msgstr "Supprimer la requête" #: templates/helpdesk/confirm_delete_saved_query.html:8 #, python-format @@ -1152,13 +1154,13 @@ msgid "" "Are you sure you want to delete this saved filter " "(%(query_title)s)? To re-create it, you will need to manually re-" "filter your ticket listing." -msgstr "" +msgstr "Êtes vous certain de vouloir supprimer ce filtre enregistré (%(query_title)s)? Pour le recréer, vous devrez refiltrer la liste de ticket manuellement." #: templates/helpdesk/confirm_delete_saved_query.html:11 msgid "" "You have shared this query, so other users may be using it. If you delete " "it, they will have to manually create their own query." -msgstr "" +msgstr "Vous avez partagé cette requête, il est donc possible que d'autres l'utilisent. Si vous la supprimez, il devront créer la leur manuellement." #: templates/helpdesk/confirm_delete_saved_query.html:14 #: templates/helpdesk/delete_ticket.html:10 @@ -1183,13 +1185,13 @@ msgstr "Soumettre un Ticket" #: templates/helpdesk/create_ticket.html:11 #: templates/helpdesk/edit_ticket.html:11 msgid "Unless otherwise stated, all fields are required." -msgstr "" +msgstr "Sauf mention contraire, tous les champs sont requis." #: templates/helpdesk/create_ticket.html:11 #: templates/helpdesk/edit_ticket.html:11 #: templates/helpdesk/public_homepage.html:28 msgid "Please provide as descriptive a title and description as possible." -msgstr "" +msgstr "Veuillez fournir un titre et une description aussi détaillés que possible." #: templates/helpdesk/create_ticket.html:30 #: templates/helpdesk/public_homepage.html:55 @@ -1205,7 +1207,7 @@ msgid "" "Welcome to your Helpdesk Dashboard! From here you can quickly see tickets " "submitted by you, tickets you are working on, and those tickets that have no" " owner." -msgstr "Bienvenue dans votre tableau de bord! D'ici vous pouvez rapidement voir les tickets que vous avez soumis, ceux sur lesquels vous travaillez et ceux sur qui n'ont pas de propriétaire." +msgstr "Bienvenue dans votre tableau de bord! D'ici vous pouvez rapidement voir les tickets que vous avez soumis, ceux sur lesquels vous travaillez et ceux qui n'ont pas de propriétaire." #: templates/helpdesk/dashboard.html:14 msgid "Helpdesk Summary" @@ -1213,37 +1215,37 @@ msgstr "Résumé Helpdesk" #: templates/helpdesk/dashboard.html:36 msgid "Current Ticket Stats" -msgstr "" +msgstr "Statistiques actuelles des tickets" #: templates/helpdesk/dashboard.html:37 msgid "Average number of days until ticket is closed (all tickets): " -msgstr "" +msgstr "Délai moyen de fermeture d'un ticket (tous tickets) :" #: templates/helpdesk/dashboard.html:38 msgid "" "Average number of days until ticket is closed (tickets opened in last 60 " "days): " -msgstr "" +msgstr "Délai moyen de fermeture d'un ticket (tickets ouverts dans les 60 derniers jours) :" #: templates/helpdesk/dashboard.html:39 msgid "Click" -msgstr "" +msgstr "Cliquer" #: templates/helpdesk/dashboard.html:39 msgid "for detailed average by month." -msgstr "" +msgstr "Pour la moyenne par mois détaillé" #: templates/helpdesk/dashboard.html:40 msgid "Distribution of open tickets, grouped by time period:" -msgstr "" +msgstr "Distribution des tickets ouverts, groupés par période temporelle :" #: templates/helpdesk/dashboard.html:41 msgid "Days since opened" -msgstr "" +msgstr "Jours passés depuis l'ouverture" #: templates/helpdesk/dashboard.html:41 msgid "Number of open tickets" -msgstr "" +msgstr "Nombre de tickets ouverts" #: templates/helpdesk/dashboard.html:57 msgid "All Tickets submitted by you" @@ -1262,7 +1264,7 @@ msgstr "Dernière mise à jour" #: templates/helpdesk/dashboard.html:77 msgid "Open Tickets assigned to you (you are working on this ticket)" -msgstr "Ouvrir les tickets qui vous sont assignés (vous travaillez sur ce ticket)" +msgstr "Tickets ouverts qui vous sont assignés (vous travaillez sur ce ticket)" #: templates/helpdesk/dashboard.html:92 msgid "You have no tickets assigned to you." @@ -1270,7 +1272,7 @@ msgstr "Vous n'avez aucun ticket qui vous est assigné." #: templates/helpdesk/dashboard.html:99 msgid "(pick up a ticket if you start to work on it)" -msgstr "" +msgstr "(assignez vous un ticket si vous commencez à travailler dessus)" #: templates/helpdesk/dashboard.html:110 #: templates/helpdesk/ticket_desc_table.html:38 @@ -1305,7 +1307,7 @@ msgid "" "Are you sure you want to delete this ticket (%(ticket_title)s)? All" " traces of the ticket, including followups, attachments, and updates will be" " irreversibly removed." -msgstr "" +msgstr "Êtes vous certain de vouloir supprimer ce ticket (%(ticket_title)s) ? Toutes les traces associées, à savoir les relances, les pièces jointes et les mises à jour seront irrémédiablement supprimés." #: templates/helpdesk/edit_ticket.html:3 msgid "Edit Ticket" @@ -1313,18 +1315,18 @@ msgstr "Editer le ticket" #: templates/helpdesk/edit_ticket.html:9 msgid "Edit a Ticket" -msgstr "" +msgstr "Modification du ticket" #: templates/helpdesk/edit_ticket.html:13 msgid "Note" -msgstr "" +msgstr "Note" #: templates/helpdesk/edit_ticket.html:13 msgid "" "Editing a ticket does not send an e-mail to the ticket owner or " "submitter. No new details should be entered, this form should only be used " "to fix incorrect details or clean up the submission." -msgstr "" +msgstr "Modifier un ticket n'envoie pas d'e-mail au propriétaire ou au rapporteur du ticket. Aucun détail ne doit être ajouté, ce formulaire doit juste être utilisé pour corriger des informations incorrectes ou nettoyer la soumission." #: templates/helpdesk/edit_ticket.html:33 msgid "Save Changes" @@ -1340,14 +1342,14 @@ msgstr "Ignorer l'adresse e-mail" msgid "" "To ignore an e-mail address and prevent any emails from that address " "creating tickets automatically, enter the e-mail address below." -msgstr "" +msgstr "Pour prévenir la réception et ignoré les courriels envoyé de cette adresse. entrez le courriel de l’adresse ci-dessous pour la création automatique de billet" #: templates/helpdesk/email_ignore_add.html:10 msgid "" "You can either enter a whole e-mail address such as " "email@domain.com or a portion of an e-mail address with a wildcard," " such as *@domain.com or user@*." -msgstr "" +msgstr "Vous pouvez inscrire une adresse de courriel complet tel que email@domain.com ou en partie avec « wildcard » Tel que *@domain.com or user@*" #: templates/helpdesk/email_ignore_del.html:3 msgid "Delete Ignored E-Mail Address" @@ -1355,7 +1357,7 @@ msgstr "Supprimer l'adresse e-mail ignorée" #: templates/helpdesk/email_ignore_del.html:6 msgid "Un-Ignore E-Mail Address" -msgstr "" +msgstr "Ne plus ignorer l'adresse e-mail" #: templates/helpdesk/email_ignore_del.html:8 #, python-format @@ -1363,7 +1365,7 @@ msgid "" "Are you sure you wish to stop removing this email address " "(%(email_address)s) and allow their e-mails to automatically create" " tickets in your system? You can re-add this e-mail address at any time." -msgstr "" +msgstr "Êtes-vous certain de vouloir retirer le courriel (%(email_address)s) et de permettre la création automatique des billets dans votre system? Vous pouvez remettre le courriel en tout temps" #: templates/helpdesk/email_ignore_del.html:10 msgid "Keep Ignoring It" @@ -1526,11 +1528,11 @@ msgstr "Statistiques" #: templates/helpdesk/navigation.html:24 msgid "Saved Query" -msgstr "" +msgstr "Requête sauvegardée" #: templates/helpdesk/navigation.html:39 msgid "Change password" -msgstr "" +msgstr "Changer le mot de passe" #: templates/helpdesk/navigation.html:50 msgid "Search..." @@ -1587,7 +1589,7 @@ msgstr "Impossible d'ouvrir le ticket" #: templates/helpdesk/public_spam.html:5 msgid "Sorry, but there has been an error trying to submit your ticket." -msgstr "" +msgstr "Désolé, une erreur est survenue en essayant de soumettre votre ticket." #: templates/helpdesk/public_spam.html:6 msgid "" @@ -1595,13 +1597,13 @@ msgid "" "unable to save it. If this is not spam, please press back and re-type your " "message. Be careful to avoid sounding 'spammy', and if you have heaps of " "links please try removing them if possible." -msgstr "" +msgstr "Notre système a classé votre soumission comme spam, alors nous dans l’impossibilité de le sauvegarder. Si ceci n’est pas du spam, svp appuyer recul et retaper votre message en s’assurant de ne pas être « Spammy », si vous avez beaucoup de Liens, svp les retirés." #: templates/helpdesk/public_spam.html:7 msgid "" "We are sorry for any inconvenience, however this check is required to avoid " "our helpdesk resources being overloaded by spammers." -msgstr "" +msgstr "Nous somme désolé pour cette inconvénients, mais cette vérification est nécessaire pour évité que notre ressource Helpdesk soit inondée par les spammeur" #: templates/helpdesk/public_view_form.html:8 msgid "Error:" @@ -1682,7 +1684,7 @@ msgstr "Rapports par File" #: templates/helpdesk/report_index.html:27 views/staff.py:1049 msgid "Days until ticket closed by Month" -msgstr "" +msgstr "Jours avant fermeture d'un ticket par mois" #: templates/helpdesk/report_output.html:19 msgid "" @@ -1695,7 +1697,7 @@ msgstr "Selectionnez une requête :" #: templates/helpdesk/report_output.html:26 msgid "Filter Report" -msgstr "" +msgstr "Filtrer le rapport" #: templates/helpdesk/report_output.html:29 msgid "" @@ -1739,7 +1741,7 @@ msgid "" "all tickets, for each of the queues in your helpdesk. For example, if you " "manage the staff who utilise a particular queue, this may be used to view " "new tickets coming into that queue." -msgstr "" +msgstr "Ces flux RSS vous permettent d’avoir un sommaire de vos billets ou tous les billets, pour chacune des files dans votre helpdesk. Par exemple si vous êtes responsable d’une file particulière, ceci vous permet de visionner tous les nouveaux billet entrant." #: templates/helpdesk/rss_list.html:23 msgid "Per-Queue Feeds" @@ -1759,7 +1761,7 @@ msgstr "Modifier les paramètres systèmes" #: templates/helpdesk/system_settings.html:8 msgid "The following items can be maintained by you or other superusers:" -msgstr "" +msgstr "Les items suivant peuvent être maintenus par vous ou par des super usagers :" #: templates/helpdesk/system_settings.html:11 msgid "E-Mail Ignore list" @@ -1889,7 +1891,7 @@ msgstr "\n

Ajouter Ticket CC

\n\n

To automatically send an email to a u #: templates/helpdesk/ticket_cc_add.html:21 msgid "Save Ticket CC" -msgstr "" +msgstr "CC sauvegarder billet" #: templates/helpdesk/ticket_cc_del.html:3 msgid "Delete Ticket CC" @@ -2011,13 +2013,13 @@ msgstr "Cliquez ici pour ajouter / supprimer des personnes qui pourrait recevoir #: templates/helpdesk/ticket_desc_table.html:53 msgid "Subscribe" -msgstr "" +msgstr "Souscrire" #: templates/helpdesk/ticket_desc_table.html:53 msgid "" "Click here to subscribe yourself to this ticket, if you want to receive an " "e-mail whenever this ticket is updated." -msgstr "" +msgstr "Cliquez ici pour souscrire à ce ticket si vous souhaitez recevoir un e-mail dès que ce dernier est mis à jour." #: templates/helpdesk/ticket_desc_table.html:57 msgid "Dependencies" @@ -2063,15 +2065,15 @@ msgstr "Mots-clés" #: templates/helpdesk/ticket_list.html:72 msgid "Date Range" -msgstr "" +msgstr "Période temporelle" #: templates/helpdesk/ticket_list.html:100 msgid "Reverse" -msgstr "" +msgstr "Renverser" #: templates/helpdesk/ticket_list.html:102 msgid "Ordering applied to tickets" -msgstr "" +msgstr "Tri appliqué aux tickets" #: templates/helpdesk/ticket_list.html:107 msgid "Owner(s)" @@ -2079,11 +2081,11 @@ msgstr "Propriétaire(s)" #: templates/helpdesk/ticket_list.html:111 msgid "(ME)" -msgstr "" +msgstr "(MOI)" #: templates/helpdesk/ticket_list.html:115 msgid "Ctrl-Click to select multiple options" -msgstr "" +msgstr "Ctrl-Click pour sélectionner plusieurs options" #: templates/helpdesk/ticket_list.html:120 msgid "Queue(s)" @@ -2092,7 +2094,7 @@ msgstr "File(s) d'attente" #: templates/helpdesk/ticket_list.html:121 #: templates/helpdesk/ticket_list.html:127 msgid "Ctrl-click to select multiple options" -msgstr "" +msgstr "Ctrl-click pour sélectionner plusieurs options" #: templates/helpdesk/ticket_list.html:126 msgid "Status(es)" @@ -2100,21 +2102,21 @@ msgstr "État(s)" #: templates/helpdesk/ticket_list.html:132 msgid "Date (From)" -msgstr "" +msgstr "Date (du)" #: templates/helpdesk/ticket_list.html:133 msgid "Date (To)" -msgstr "" +msgstr "Date (au)" #: templates/helpdesk/ticket_list.html:134 msgid "Use YYYY-MM-DD date format, eg 2011-05-29" -msgstr "" +msgstr "Utilisez le format de date AAAA-MM-JJ, ex 2011-05-29" #: templates/helpdesk/ticket_list.html:140 msgid "" "Keywords are case-insensitive, and will be looked for in the title, body and" " submitter fields." -msgstr "" +msgstr "Les mots clés sont insensibles à la case et seront appliqués aux champs titre, corps de texte et rapporteur." #: templates/helpdesk/ticket_list.html:144 msgid "Apply Filter" @@ -2123,14 +2125,14 @@ msgstr "Appliquer le filtre" #: templates/helpdesk/ticket_list.html:146 #, python-format msgid "You are currently viewing saved query \"%(query_name)s\"." -msgstr "" +msgstr "Vous visionnez la requête \\\"%(query_name)s\\\"." #: templates/helpdesk/ticket_list.html:149 #, python-format msgid "" "Run a report on this " "query to see stats and charts for the data listed below." -msgstr "" +msgstr "Exécuté un rapport surcette requête pour voir les statistique et graphique pour les data ci-dessous." #: templates/helpdesk/ticket_list.html:162 #: templates/helpdesk/ticket_list.html:181 @@ -2197,7 +2199,7 @@ msgstr "Aucune" #: templates/helpdesk/ticket_list.html:260 msgid "Inverse" -msgstr "" +msgstr "Inverser" #: templates/helpdesk/ticket_list.html:262 msgid "With Selected Tickets:" @@ -2235,7 +2237,7 @@ msgstr "Modifier les paramètres de l'utilisateur" msgid "" "Use the following options to change the way your helpdesk system works for " "you. These settings do not impact any other user." -msgstr "" +msgstr "Utilisez les options ci-dessous pour changer personnaliser le fonctionnement du centre d'assistance. Ces paramètres n'impactent pas les autres utilisateurs." #: templates/helpdesk/user_settings.html:14 msgid "Save Options" @@ -2260,7 +2262,7 @@ msgstr "Identifiant Helpdesk" #: templates/helpdesk/registration/login.html:14 msgid "To log in simply enter your username and password below." -msgstr "" +msgstr "Renseignez votre nom d'utilisateur et votre mot de passe ci-dessous pour vous connecter." #: templates/helpdesk/registration/login.html:17 msgid "Your username and password didn't match. Please try again." diff --git a/helpdesk/locale/hr/LC_MESSAGES/django.mo b/helpdesk/locale/hr/LC_MESSAGES/django.mo index 7b412fd7..f23d6077 100644 Binary files a/helpdesk/locale/hr/LC_MESSAGES/django.mo and b/helpdesk/locale/hr/LC_MESSAGES/django.mo differ diff --git a/helpdesk/locale/hr/LC_MESSAGES/django.po b/helpdesk/locale/hr/LC_MESSAGES/django.po index a45c4ddb..0abc0bb1 100644 --- a/helpdesk/locale/hr/LC_MESSAGES/django.po +++ b/helpdesk/locale/hr/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # Translators: +# Alan Pevec , 2016 msgid "" msgstr "" "Project-Id-Version: django-helpdesk\n" "Report-Msgid-Bugs-To: http://github.com/RossP/django-helpdesk/issues\n" "POT-Creation-Date: 2014-07-26 14:14+0200\n" -"PO-Revision-Date: 2014-08-01 09:58+0000\n" -"Last-Translator: Ross Poulton \n" -"Language-Team: Croatian (http://www.transifex.com/projects/p/django-helpdesk/language/hr/)\n" +"PO-Revision-Date: 2016-10-09 16:56+0000\n" +"Last-Translator: Alan Pevec \n" +"Language-Team: Croatian (http://www.transifex.com/rossp/django-helpdesk/language/hr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -27,29 +28,29 @@ msgstr "" #: templates/helpdesk/ticket_list.html:225 views/staff.py:1032 #: views/staff.py:1038 views/staff.py:1044 views/staff.py:1050 msgid "Queue" -msgstr "" +msgstr "red" #: forms.py:137 msgid "Summary of the problem" -msgstr "" +msgstr "sažetak problema" #: forms.py:142 msgid "Submitter E-Mail Address" -msgstr "" +msgstr "adresa podnositelja" #: forms.py:144 msgid "" "This e-mail address will receive copies of all public updates to this " "ticket." -msgstr "" +msgstr "Ova adresa će primiti kopije svih javnih ažuriranja ovog problema." #: forms.py:150 msgid "Description of Issue" -msgstr "" +msgstr "opis problema" #: forms.py:157 msgid "Case owner" -msgstr "" +msgstr "vlasnik slučaja" #: forms.py:158 msgid "" @@ -63,59 +64,59 @@ msgstr "" #: templates/helpdesk/ticket_desc_table.html:47 #: templates/helpdesk/ticket_list.html:94 views/staff.py:429 msgid "Priority" -msgstr "" +msgstr "prioritet" #: forms.py:167 msgid "Please select a priority carefully. If unsure, leave it as '3'." -msgstr "" +msgstr "Pažljivo odredite prioritet. Ako niste sigurni, ostavite '3'." #: forms.py:174 forms.py:365 models.py:335 templates/helpdesk/ticket.html:186 #: views/staff.py:439 msgid "Due on" -msgstr "" +msgstr "Rok izvršenja" #: forms.py:186 forms.py:370 msgid "Attach File" -msgstr "" +msgstr "priloži datoteku" #: forms.py:187 forms.py:371 msgid "You can attach a file such as a document or screenshot to this ticket." -msgstr "" +msgstr "Možete priložiti datoteku npr. dokument ili sliku ekrana." #: forms.py:240 msgid "Ticket Opened" -msgstr "" +msgstr "otvoreni slučaj" #: forms.py:247 #, python-format msgid "Ticket Opened & Assigned to %(name)s" -msgstr "" +msgstr "Slučaj otvoren i dodijeljen %(name)s" #: forms.py:337 msgid "Summary of your query" -msgstr "" +msgstr "Sažetak Vašeg upita" #: forms.py:342 msgid "Your E-Mail Address" -msgstr "" +msgstr "adresa Vaše elektroničke pošte" #: forms.py:343 msgid "We will e-mail you when your ticket is updated." -msgstr "" +msgstr "Poslat ćemo Vam poruku kad Vaš slučaj bude ažuriran." #: forms.py:348 msgid "Description of your issue" -msgstr "" +msgstr "opis Vašeg prolema" #: forms.py:350 msgid "" "Please be as descriptive as possible, including any details we may need to " "address your query." -msgstr "" +msgstr "Budite što je moguće jasniji i uključite sve detalje koji nam trebaju za rješavanje Vašeg upita." #: forms.py:358 msgid "Urgency" -msgstr "" +msgstr "hitnost" #: forms.py:359 msgid "Please select a priority carefully." @@ -123,11 +124,11 @@ msgstr "" #: forms.py:419 msgid "Ticket Opened Via Web" -msgstr "" +msgstr "Slučaj otvoren na webu" #: forms.py:486 msgid "Show Ticket List on Login?" -msgstr "" +msgstr "Prikaži listu slučajeva prilikom prijave?" #: forms.py:487 msgid "Display the ticket list upon login? Otherwise, the dashboard is shown." @@ -185,7 +186,7 @@ msgstr "" #: templates/helpdesk/ticket.html:178 templates/helpdesk/ticket_list.html:85 #: templates/helpdesk/ticket_list.html:225 views/staff.py:419 msgid "Title" -msgstr "" +msgstr "naslov" #: models.py:40 models.py:822 models.py:1206 msgid "Slug" @@ -201,7 +202,7 @@ msgstr "" #: templates/helpdesk/email_ignore_list.html:13 #: templates/helpdesk/ticket_cc_list.html:15 msgid "E-Mail Address" -msgstr "" +msgstr "adresa elektroničke pošte" #: models.py:49 msgid "" @@ -229,7 +230,7 @@ msgstr "" #: models.py:71 msgid "Allow E-Mail Submission?" -msgstr "" +msgstr "Dozvoli prijave elektroničkom poštom?" #: models.py:74 msgid "Do you want to poll the e-mail box below for new tickets?" @@ -273,11 +274,11 @@ msgstr "" #: models.py:110 msgid "POP 3" -msgstr "" +msgstr "POP 3" #: models.py:110 msgid "IMAP" -msgstr "" +msgstr "IMAP" #: models.py:113 msgid "" @@ -353,30 +354,30 @@ msgstr "" #: models.py:191 templates/helpdesk/email_ignore_list.html:13 msgid "Queues" -msgstr "" +msgstr "redovi" #: models.py:245 templates/helpdesk/dashboard.html:15 #: templates/helpdesk/ticket.html:138 msgid "Open" -msgstr "" +msgstr "otvoreno" #: models.py:246 templates/helpdesk/ticket.html:144 #: templates/helpdesk/ticket.html.py:150 templates/helpdesk/ticket.html:155 #: templates/helpdesk/ticket.html.py:159 msgid "Reopened" -msgstr "" +msgstr "ponovno otvoreno" #: models.py:247 templates/helpdesk/dashboard.html:15 #: templates/helpdesk/ticket.html:139 templates/helpdesk/ticket.html.py:145 #: templates/helpdesk/ticket.html:151 msgid "Resolved" -msgstr "" +msgstr "riješeno" #: models.py:248 templates/helpdesk/dashboard.html:15 #: templates/helpdesk/ticket.html:140 templates/helpdesk/ticket.html.py:146 #: templates/helpdesk/ticket.html:152 templates/helpdesk/ticket.html.py:156 msgid "Closed" -msgstr "" +msgstr "zatvoreno" #: models.py:249 templates/helpdesk/ticket.html:141 #: templates/helpdesk/ticket.html.py:147 templates/helpdesk/ticket.html:160 @@ -695,7 +696,7 @@ msgstr "" #: models.py:788 msgid "HTML" -msgstr "" +msgstr "HTML" #: models.py:789 msgid "The same context is available here as in plain_text, above." @@ -724,15 +725,15 @@ msgstr "" #: models.py:849 templates/helpdesk/kb_index.html:11 #: templates/helpdesk/public_homepage.html:11 msgid "Category" -msgstr "" +msgstr "kategorija" #: models.py:858 msgid "Question" -msgstr "" +msgstr "pitanje" #: models.py:862 msgid "Answer" -msgstr "" +msgstr "odgovor" #: models.py:866 msgid "Votes" @@ -752,7 +753,7 @@ msgstr "" #: models.py:878 msgid "Last Updated" -msgstr "" +msgstr "zadnje ažuriranje" #: models.py:879 msgid "The date on which this question was most recently changed." @@ -1087,7 +1088,7 @@ msgstr "" #: templates/helpdesk/attribution.html:2 msgid "" "django-helpdesk." -msgstr "" +msgstr "django-helpdesk." #: templates/helpdesk/base.html:10 msgid "Powered by django-helpdesk" @@ -1110,7 +1111,7 @@ msgstr "" #: templates/helpdesk/base.html:52 templates/helpdesk/public_base.html:6 #: templates/helpdesk/public_base.html:18 msgid "Helpdesk" -msgstr "" +msgstr "Helpdesk" #: templates/helpdesk/base.html:62 templates/helpdesk/rss_list.html:9 #: templates/helpdesk/rss_list.html:12 templates/helpdesk/rss_list.html:15 @@ -2053,7 +2054,7 @@ msgstr "" #: templates/helpdesk/ticket_list.html:71 #: templates/helpdesk/ticket_list.html:139 msgid "Keywords" -msgstr "" +msgstr "ključne riječi" #: templates/helpdesk/ticket_list.html:72 msgid "Date Range" diff --git a/helpdesk/locale/ru/LC_MESSAGES/django.mo b/helpdesk/locale/ru/LC_MESSAGES/django.mo index 837ac3a9..9fc44af5 100644 Binary files a/helpdesk/locale/ru/LC_MESSAGES/django.mo and b/helpdesk/locale/ru/LC_MESSAGES/django.mo differ diff --git a/helpdesk/locale/ru/LC_MESSAGES/django.po b/helpdesk/locale/ru/LC_MESSAGES/django.po index 405cce3f..bf2a6761 100644 --- a/helpdesk/locale/ru/LC_MESSAGES/django.po +++ b/helpdesk/locale/ru/LC_MESSAGES/django.po @@ -1,9 +1,11 @@ # django-helpdesk English language translation # Copyright (C) 2011 Ross Poulton # This file is distributed under the same license as the django-helpdesk package. -# +# +# Translators: # Translators: # Антон Комолов , 2011 +# Dmitry Sharavyov , 2016 # gorblnu4 , 2011 # Ross Poulton , 2011 # Антон Комолов , 2011 @@ -11,1058 +13,1159 @@ msgid "" msgstr "" "Project-Id-Version: django-helpdesk\n" "Report-Msgid-Bugs-To: http://github.com/RossP/django-helpdesk/issues\n" -"POT-Creation-Date: 2012-08-07 20:40+1000\n" -"PO-Revision-Date: 2013-04-29 09:18+0000\n" -"Last-Translator: Ross Poulton \n" -"Language-Team: Russian (http://www.transifex.com/projects/p/django-helpdesk/language/ru/)\n" +"POT-Creation-Date: 2014-07-26 14:14+0200\n" +"PO-Revision-Date: 2016-07-25 22:09+0000\n" +"Last-Translator: Dmitry Sharavyov \n" +"Language-Team: Russian (http://www.transifex.com/rossp/django-helpdesk/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\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" +"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" -#: forms.py:113 forms.py:360 models.py:262 -#: templates/helpdesk/dashboard.html:11 templates/helpdesk/dashboard.html:37 -#: templates/helpdesk/dashboard.html:57 templates/helpdesk/dashboard.html:77 -#: templates/helpdesk/dashboard.html:99 templates/helpdesk/rss_list.html:23 -#: templates/helpdesk/ticket_list.html:56 -#: templates/helpdesk/ticket_list.html:78 -#: templates/helpdesk/ticket_list.html:199 views/staff.py:976 -#: views/staff.py:982 views/staff.py:988 +#: forms.py:128 forms.py:328 models.py:190 models.py:267 +#: templates/helpdesk/dashboard.html:15 templates/helpdesk/dashboard.html:58 +#: templates/helpdesk/dashboard.html:78 templates/helpdesk/dashboard.html:100 +#: templates/helpdesk/dashboard.html:124 templates/helpdesk/rss_list.html:24 +#: templates/helpdesk/ticket_list.html:69 +#: templates/helpdesk/ticket_list.html:88 +#: templates/helpdesk/ticket_list.html:225 views/staff.py:1032 +#: views/staff.py:1038 views/staff.py:1044 views/staff.py:1050 msgid "Queue" msgstr "Очередь" -#: forms.py:122 +#: forms.py:137 msgid "Summary of the problem" msgstr "Краткое описание проблемы" -#: forms.py:127 +#: forms.py:142 msgid "Submitter E-Mail Address" msgstr "Адрес электронной почты отправителя" -#: forms.py:129 +#: forms.py:144 msgid "" "This e-mail address will receive copies of all public updates to this " "ticket." msgstr "На этот адрес электронной почты будут посылаться копии всех публичных обновлений этого тикета" -#: forms.py:135 +#: forms.py:150 msgid "Description of Issue" msgstr "Описание проблемы" -#: forms.py:142 +#: forms.py:157 msgid "Case owner" msgstr "Владелец" -#: forms.py:143 +#: forms.py:158 msgid "" "If you select an owner other than yourself, they'll be e-mailed details of " "this ticket immediately." msgstr "Если вы выберете отличного от себя владельца, ему будут высланы детали этого тикета немедленно." -#: forms.py:151 models.py:322 management/commands/escalate_tickets.py:149 -#: templates/helpdesk/public_view_ticket.html:21 -#: templates/helpdesk/ticket.html:176 -#: templates/helpdesk/ticket_desc_table.html:31 -#: templates/helpdesk/ticket_list.html:84 views/staff.py:355 +#: forms.py:166 models.py:327 management/commands/escalate_tickets.py:154 +#: templates/helpdesk/public_view_ticket.html:23 +#: templates/helpdesk/ticket.html:184 +#: templates/helpdesk/ticket_desc_table.html:47 +#: templates/helpdesk/ticket_list.html:94 views/staff.py:429 msgid "Priority" msgstr "Приоритет" -#: forms.py:152 +#: forms.py:167 msgid "Please select a priority carefully. If unsure, leave it as '3'." -msgstr "Пожалуйста выбирайте приоритет внимательно. Если не уверены оставьте 3, как есть." +msgstr "Пожалуйста, выбирайте приоритет внимательно. Если не уверены, оставьте 3, как есть." -#: forms.py:159 forms.py:397 models.py:330 templates/helpdesk/ticket.html:178 -#: views/staff.py:365 +#: forms.py:174 forms.py:365 models.py:335 templates/helpdesk/ticket.html:186 +#: views/staff.py:439 msgid "Due on" msgstr "Выполнить до" -#: forms.py:171 forms.py:402 +#: forms.py:186 forms.py:370 msgid "Attach File" msgstr "Прикрепить файл" -#: forms.py:172 forms.py:403 +#: forms.py:187 forms.py:371 msgid "You can attach a file such as a document or screenshot to this ticket." -msgstr "Вы можете прикрепить файл, например, документ или скриншот к тикету." +msgstr "Вы можете прикрепить файл, например, документ или скриншот, к тикету." -#: forms.py:180 templates/helpdesk/public_view_ticket.html:33 -#: templates/helpdesk/ticket.html:182 -#: templates/helpdesk/ticket_desc_table.html:42 -#: templates/helpdesk/ticket_list.html:61 -#: templates/helpdesk/ticket_list.html:199 views/staff.py:376 -msgid "Tags" -msgstr "Тэги" - -#: forms.py:181 -msgid "" -"Words, separated by spaces, or phrases separated by commas. These should " -"communicate significant characteristics of this ticket" -msgstr "Слова, разделенные пробелами, или фразы, разделенные запятыми. Они должны обобщать значимые характеристики этого тикета" - -#: forms.py:275 +#: forms.py:240 msgid "Ticket Opened" msgstr "Тикет открыт" -#: forms.py:282 +#: forms.py:247 #, python-format msgid "Ticket Opened & Assigned to %(name)s" msgstr "Тикет открыт и назначен %(name)s" -#: forms.py:369 +#: forms.py:337 msgid "Summary of your query" msgstr "Краткое описание вашего запроса" -#: forms.py:374 +#: forms.py:342 msgid "Your E-Mail Address" msgstr "Ваш адрес электронной почты" -#: forms.py:375 +#: forms.py:343 msgid "We will e-mail you when your ticket is updated." msgstr "Мы известим вас по электронной почте, когда тикет обновится." -#: forms.py:380 +#: forms.py:348 msgid "Description of your issue" msgstr "Описание вашей проблемы." -#: forms.py:382 +#: forms.py:350 msgid "" "Please be as descriptive as possible, including any details we may need to " "address your query." msgstr "Пожалуйста, будьте максимально информативным, нам пригодятся любые подробности касающиеся вашего запроса." -#: forms.py:390 +#: forms.py:358 msgid "Urgency" msgstr "Срочность" -#: forms.py:391 +#: forms.py:359 msgid "Please select a priority carefully." msgstr "Пожалуйста, тщательно выберите приоритеты." -#: forms.py:486 +#: forms.py:419 msgid "Ticket Opened Via Web" msgstr "Тикет открыт через Web" -#: forms.py:553 +#: forms.py:486 msgid "Show Ticket List on Login?" msgstr "Показывать список тикетов после входа?" -#: forms.py:554 +#: forms.py:487 msgid "Display the ticket list upon login? Otherwise, the dashboard is shown." msgstr "Показывать список тикетов после входа? Иначе будет показана панель." -#: forms.py:559 +#: forms.py:492 msgid "E-mail me on ticket change?" msgstr "Уведомлять меня по электронной почте о изменениях тикета?" -#: forms.py:560 +#: forms.py:493 msgid "" "If you're the ticket owner and the ticket is changed via the web by somebody" " else, do you want to receive an e-mail?" msgstr "Если вы владелец тикета и тикет меняется через web кем-то еще, вы хотите получить уведомление по электронной почте?" -#: forms.py:565 +#: forms.py:498 msgid "E-mail me when assigned a ticket?" msgstr "Уведомить меня по электронной почте о назначенных мне тикетах?" -#: forms.py:566 +#: forms.py:499 msgid "" "If you are assigned a ticket via the web, do you want to receive an e-mail?" msgstr "Хотите ли получать уведомления по электронной почте если кто-то назначил вам тикет через web?" -#: forms.py:571 +#: forms.py:504 msgid "E-mail me when a ticket is changed via the API?" msgstr "Уведомить меня когда тикет изменён через API?" -#: forms.py:572 +#: forms.py:505 msgid "If a ticket is altered by the API, do you want to receive an e-mail?" msgstr "Хотите ли вы получать электронное уведомление если тикет был изменён через API" -#: forms.py:577 +#: forms.py:510 msgid "Number of tickets to show per page" msgstr "Количество тикетов на страницу" -#: forms.py:578 +#: forms.py:511 msgid "How many tickets do you want to see on the Ticket List page?" msgstr "Как много тикетов вы хотите видеть на странице?" -#: forms.py:585 +#: forms.py:518 msgid "Use my e-mail address when submitting tickets?" msgstr "Использовать мой адрес электронной почты при отправке тикета?" -#: forms.py:586 +#: forms.py:519 msgid "" "When you submit a ticket, do you want to automatically use your e-mail " "address as the submitter address? You can type a different e-mail address " "when entering the ticket if needed, this option only changes the default." msgstr "Когда вы отправляете тикет, вы хотите, чтобы автоматически использовался ваш адрес электронной почты в качестве отправителя? Вы можете ввести другой адрес электронной почты при создании тикета в случае необходимости. Этот вариант только изменит значение по умолчанию." -#: models.py:32 models.py:256 models.py:490 models.py:787 models.py:821 -#: templates/helpdesk/dashboard.html:37 templates/helpdesk/dashboard.html:57 -#: templates/helpdesk/dashboard.html:77 templates/helpdesk/dashboard.html:99 -#: templates/helpdesk/ticket.html:170 templates/helpdesk/ticket_list.html:75 -#: templates/helpdesk/ticket_list.html:199 views/staff.py:345 +#: models.py:35 models.py:261 models.py:503 models.py:817 models.py:853 +#: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 +#: templates/helpdesk/dashboard.html:100 templates/helpdesk/dashboard.html:124 +#: templates/helpdesk/ticket.html:178 templates/helpdesk/ticket_list.html:85 +#: templates/helpdesk/ticket_list.html:225 views/staff.py:419 msgid "Title" msgstr "Заголовок" -#: models.py:37 models.py:792 models.py:1162 +#: models.py:40 models.py:822 models.py:1206 msgid "Slug" msgstr "ЧПУ" -#: models.py:38 +#: models.py:41 msgid "" "This slug is used when building ticket ID's. Once set, try not to change it " "or e-mailing may get messy." msgstr "Эта строка используется для конструирования идентификатора тикета. Однажды установив, старайтесь не менять его, или электронная почта может перепутаться." -#: models.py:43 models.py:1015 models.py:1085 models.py:1159 +#: models.py:46 models.py:1054 models.py:1129 models.py:1203 #: templates/helpdesk/email_ignore_list.html:13 #: templates/helpdesk/ticket_cc_list.html:15 msgid "E-Mail Address" msgstr "Адрес электронной почты" -#: models.py:46 +#: models.py:49 msgid "" "All outgoing e-mails for this queue will use this e-mail address. If you use" " IMAP or POP3, this should be the e-mail address for that mailbox." msgstr "Все исходящие электронные письма этой очереди будут использовать этот электронный адрес. Если вы используете IMAP или POP3 это и есть этот электронный адрес." -#: models.py:52 models.py:766 +#: models.py:55 models.py:794 msgid "Locale" msgstr "Локаль" -#: models.py:56 +#: models.py:59 msgid "" "Locale of this queue. All correspondence in this queue will be in this " "language." msgstr "Локаль этой очереди. Вся переписка в этой очереди будет на этом языке." -#: models.py:60 +#: models.py:63 msgid "Allow Public Submission?" msgstr "Разрешить общедоступное размещение тикетов?" -#: models.py:63 +#: models.py:66 msgid "Should this queue be listed on the public submission form?" msgstr "Должна ли эта очередь быть доступна в публичной форме заявки?" -#: models.py:68 +#: models.py:71 msgid "Allow E-Mail Submission?" msgstr "Разрешить размещение тикета через электронную почту?" -#: models.py:71 +#: models.py:74 msgid "Do you want to poll the e-mail box below for new tickets?" msgstr "Хотите ли вы опрашивать ниже указанный электронный адрес на наличие новых тикетов?" -#: models.py:76 +#: models.py:79 msgid "Escalation Days" msgstr "Дни поднятия" -#: models.py:79 +#: models.py:82 msgid "" "For tickets which are not held, how often do you wish to increase their " "priority? Set to 0 for no escalation." msgstr "Как часто вы желаете увеличивать их приоритет для тикетов которые не на удержании? 0 для отключения подъёма." -#: models.py:84 +#: models.py:87 msgid "New Ticket CC Address" msgstr "Поле \"Копия\" нового тикета" -#: models.py:88 +#: models.py:91 msgid "" "If an e-mail address is entered here, then it will receive notification of " "all new tickets created for this queue. Enter a comma between multiple " "e-mail addresses." msgstr "Если здесь ввести адрес электронной почты, то он будет получать уведомления обо всех новых тикетах, созданных в этой очереди. Введите запятую между несколькими адресами электронной почты." -#: models.py:94 +#: models.py:97 msgid "Updated Ticket CC Address" msgstr "Поле \"Копия\" обновлённого тикета" -#: models.py:98 +#: models.py:101 msgid "" "If an e-mail address is entered here, then it will receive notification of " "all activity (new tickets, closed tickets, updates, reassignments, etc) for " "this queue. Separate multiple addresses with a comma." msgstr "Если ввести здесь адрес электронной почты, то он будет получать уведомления о всей деятельности (новые тикеты, закрытие тикета, обновления, назначений и т.д.) в данной очереди. Разделяйте адреса запятыми." -#: models.py:105 +#: models.py:108 msgid "E-Mail Box Type" msgstr "Тип электронного ящика" -#: models.py:107 +#: models.py:110 msgid "POP 3" msgstr "POP3" -#: models.py:107 +#: models.py:110 msgid "IMAP" msgstr "IMAP" -#: models.py:110 +#: models.py:113 msgid "" "E-Mail server type for creating tickets automatically from a mailbox - both " "POP3 and IMAP are supported." msgstr "Тип ящика электронной почты, из которого будут создаваться автоматические тикета - оба POP3 и IMAP поддерживаются." -#: models.py:115 +#: models.py:118 msgid "E-Mail Hostname" msgstr "Имя сервера электронной почты" -#: models.py:119 +#: models.py:122 msgid "" "Your e-mail server address - either the domain name or IP address. May be " "\"localhost\"." msgstr "Адрес вашего сервера электронной почты - может быть имя, или IP адрес. Или даже \"localhost\"." -#: models.py:124 +#: models.py:127 msgid "E-Mail Port" msgstr "Порт электронный почты" -#: models.py:127 +#: models.py:130 msgid "" "Port number to use for accessing e-mail. Default for POP3 is \"110\", and " "for IMAP is \"143\". This may differ on some servers. Leave it blank to use " "the defaults." msgstr "Номер порта для доступа к электронному ящику. По умолчанию \"110\" для POP3, и \"143\" для IMAP. Настройки могут отличатся на разных серверах. Оставьте пустым для использования значения по умолчанию." -#: models.py:133 +#: models.py:136 msgid "Use SSL for E-Mail?" msgstr "Использовать SSL для электронной почты?" -#: models.py:136 +#: models.py:139 msgid "" "Whether to use SSL for IMAP or POP3 - the default ports when using SSL are " "993 for IMAP and 995 for POP3." msgstr "Использовать SSL для IMAP или POP3 - порты по умолчанию для SSL 993 для IMAP и 995 для POP3." -#: models.py:141 +#: models.py:144 msgid "E-Mail Username" msgstr "Имя пользователя электронной почты" -#: models.py:145 +#: models.py:148 msgid "Username for accessing this mailbox." msgstr "Имя пользователя для доступа к этому электронному ящику." -#: models.py:149 +#: models.py:152 msgid "E-Mail Password" msgstr "Пароль электронной почты" -#: models.py:153 +#: models.py:156 msgid "Password for the above username" msgstr "Пароль для выше указанного имени пользователя" -#: models.py:157 +#: models.py:160 msgid "IMAP Folder" msgstr "Папка IMAP" -#: models.py:161 +#: models.py:164 msgid "" "If using IMAP, what folder do you wish to fetch messages from? This allows " "you to use one IMAP account for multiple queues, by filtering messages on " "your IMAP server into separate folders. Default: INBOX." msgstr "Если используется IMAP, из какой папки вы желаете скачивать сообщения? Фильтрация сообщений на сервере позволяет вам использовать один IMAP аккаунт для множества очередей. По умолчанию: INBOX." -#: models.py:168 +#: models.py:171 msgid "E-Mail Check Interval" msgstr "Интервал проверки электронной почты" -#: models.py:169 +#: models.py:172 msgid "How often do you wish to check this mailbox? (in Minutes)" msgstr "Как часто вы хотите проверять этот ящик? (в минутах)" -#: models.py:240 templates/helpdesk/dashboard.html:11 -#: templates/helpdesk/ticket.html:130 +#: models.py:191 templates/helpdesk/email_ignore_list.html:13 +msgid "Queues" +msgstr "Очереди" + +#: models.py:245 templates/helpdesk/dashboard.html:15 +#: templates/helpdesk/ticket.html:138 msgid "Open" msgstr "Открытый" -#: models.py:241 templates/helpdesk/ticket.html:136 -#: templates/helpdesk/ticket.html.py:142 templates/helpdesk/ticket.html:147 -#: templates/helpdesk/ticket.html.py:151 +#: models.py:246 templates/helpdesk/ticket.html:144 +#: templates/helpdesk/ticket.html.py:150 templates/helpdesk/ticket.html:155 +#: templates/helpdesk/ticket.html.py:159 msgid "Reopened" msgstr "Переоткрытый" -#: models.py:242 templates/helpdesk/dashboard.html:11 -#: templates/helpdesk/ticket.html:131 templates/helpdesk/ticket.html.py:137 -#: templates/helpdesk/ticket.html:143 +#: models.py:247 templates/helpdesk/dashboard.html:15 +#: templates/helpdesk/ticket.html:139 templates/helpdesk/ticket.html.py:145 +#: templates/helpdesk/ticket.html:151 msgid "Resolved" msgstr "Решённый" -#: models.py:243 templates/helpdesk/dashboard.html:11 -#: templates/helpdesk/ticket.html:132 templates/helpdesk/ticket.html.py:138 -#: templates/helpdesk/ticket.html:144 templates/helpdesk/ticket.html.py:148 +#: models.py:248 templates/helpdesk/dashboard.html:15 +#: templates/helpdesk/ticket.html:140 templates/helpdesk/ticket.html.py:146 +#: templates/helpdesk/ticket.html:152 templates/helpdesk/ticket.html.py:156 msgid "Closed" msgstr "Закрытый" -#: models.py:244 templates/helpdesk/ticket.html:133 -#: templates/helpdesk/ticket.html.py:139 templates/helpdesk/ticket.html:152 +#: models.py:249 templates/helpdesk/ticket.html:141 +#: templates/helpdesk/ticket.html.py:147 templates/helpdesk/ticket.html:160 msgid "Duplicate" msgstr "Дубликат" -#: models.py:248 +#: models.py:253 msgid "1. Critical" msgstr "1. Критичный" -#: models.py:249 +#: models.py:254 msgid "2. High" msgstr "2. Высокий" -#: models.py:250 +#: models.py:255 msgid "3. Normal" msgstr "3. Нормальный" -#: models.py:251 +#: models.py:256 msgid "4. Low" msgstr "4. Низкий" -#: models.py:252 +#: models.py:257 msgid "5. Very Low" msgstr "5. Очень низкий" -#: models.py:266 templates/helpdesk/dashboard.html:77 -#: templates/helpdesk/ticket_list.html:72 -#: templates/helpdesk/ticket_list.html:199 +#: models.py:271 templates/helpdesk/dashboard.html:100 +#: templates/helpdesk/ticket_list.html:82 +#: templates/helpdesk/ticket_list.html:225 msgid "Created" msgstr "Создан" -#: models.py:268 +#: models.py:273 msgid "Date this ticket was first created" msgstr "Дата создания этого талона" -#: models.py:272 +#: models.py:277 msgid "Modified" msgstr "Изменённый" -#: models.py:274 +#: models.py:279 msgid "Date this ticket was most recently changed." msgstr "Дата когда тикет был последний раз изменён." -#: models.py:278 templates/helpdesk/public_view_ticket.html:16 -#: templates/helpdesk/ticket_desc_table.html:26 +#: models.py:283 templates/helpdesk/public_view_ticket.html:18 +#: templates/helpdesk/ticket_desc_table.html:42 msgid "Submitter E-Mail" msgstr "Электронный адрес отправителя" -#: models.py:281 +#: models.py:286 msgid "" "The submitter will receive an email for all public follow-ups left for this " "task." msgstr "Отправитель будет получать электронные сообщения обо всех публичных дополнениях к этой задаче." -#: models.py:290 +#: models.py:295 msgid "Assigned to" msgstr "Связан с" -#: models.py:294 templates/helpdesk/dashboard.html:37 -#: templates/helpdesk/dashboard.html:57 templates/helpdesk/dashboard.html:99 -#: templates/helpdesk/ticket_list.html:57 -#: templates/helpdesk/ticket_list.html:81 -#: templates/helpdesk/ticket_list.html:199 +#: models.py:299 templates/helpdesk/dashboard.html:58 +#: templates/helpdesk/dashboard.html:78 templates/helpdesk/dashboard.html:124 +#: templates/helpdesk/ticket_list.html:70 +#: templates/helpdesk/ticket_list.html:91 +#: templates/helpdesk/ticket_list.html:225 msgid "Status" msgstr "Статус" -#: models.py:300 +#: models.py:305 msgid "On Hold" msgstr "Удерживаемый" -#: models.py:303 +#: models.py:308 msgid "If a ticket is on hold, it will not automatically be escalated." msgstr "Если тикет на удержании он не будет автоматически поднят." -#: models.py:308 models.py:796 templates/helpdesk/public_view_ticket.html:39 -#: templates/helpdesk/ticket_desc_table.html:67 +#: models.py:313 models.py:826 templates/helpdesk/public_view_ticket.html:41 +#: templates/helpdesk/ticket_desc_table.html:19 msgid "Description" msgstr "Описание" -#: models.py:311 +#: models.py:316 msgid "The content of the customers query." msgstr "Содержимое запроса клиента." -#: models.py:315 templates/helpdesk/public_view_ticket.html:46 -#: templates/helpdesk/ticket_desc_table.html:74 +#: models.py:320 templates/helpdesk/public_view_ticket.html:48 +#: templates/helpdesk/ticket_desc_table.html:26 msgid "Resolution" msgstr "Решение" -#: models.py:318 +#: models.py:323 msgid "The resolution provided to the customer by our staff." msgstr "Решение предоставлено клиенту нашими сотрудниками." -#: models.py:326 +#: models.py:331 msgid "1 = Highest Priority, 5 = Low Priority" msgstr "1 = Наивысший Приоритет, 5 = Низший Приоритет" -#: models.py:339 +#: models.py:344 msgid "" "The date this ticket was last escalated - updated automatically by " "management/commands/escalate_tickets.py." msgstr "Дата когда тикет последний раз поднят, автоматически обновляется вызовом management/commands/escalate_tickets.py." -#: models.py:348 templates/helpdesk/ticket_desc_table.html:22 -#: views/feeds.py:91 views/feeds.py:117 views/feeds.py:169 views/staff.py:302 +#: models.py:353 templates/helpdesk/ticket_desc_table.html:38 +#: views/feeds.py:95 views/feeds.py:121 views/feeds.py:173 views/staff.py:376 msgid "Unassigned" msgstr "Неназначенный" -#: models.py:387 +#: models.py:392 msgid " - On Hold" msgstr " - На Удержании" -#: models.py:481 models.py:1073 models.py:1231 models.py:1256 -#: templates/helpdesk/public_homepage.html:26 +#: models.py:394 +msgid " - Open dependencies" +msgstr "" + +#: models.py:448 models.py:494 models.py:1117 models.py:1280 models.py:1309 +#: templates/helpdesk/public_homepage.html:78 #: templates/helpdesk/public_view_form.html:12 msgid "Ticket" msgstr "Талон" -#: models.py:485 models.py:714 models.py:1008 models.py:1156 +#: models.py:449 templates/helpdesk/navigation.html:17 +#: templates/helpdesk/ticket_list.html:2 +#: templates/helpdesk/ticket_list.html:224 +msgid "Tickets" +msgstr "Тикеты" + +#: models.py:498 models.py:738 models.py:1047 models.py:1200 msgid "Date" msgstr "Дата" -#: models.py:497 views/staff.py:316 +#: models.py:510 views/staff.py:390 msgid "Comment" msgstr "Комментарий" -#: models.py:503 +#: models.py:516 msgid "Public" msgstr "Публичный" -#: models.py:506 +#: models.py:519 msgid "" "Public tickets are viewable by the submitter and all staff, but non-public " "tickets can only be seen by staff." msgstr "Публичные талоны видны отправителям и коллективу, а не публичные только коллективу." -#: models.py:514 models.py:888 models.py:1081 views/staff.py:952 -#: views/staff.py:958 views/staff.py:964 views/staff.py:970 +#: models.py:527 models.py:922 models.py:1125 views/staff.py:1008 +#: views/staff.py:1014 views/staff.py:1020 views/staff.py:1026 msgid "User" msgstr "Пользователь" -#: models.py:518 templates/helpdesk/ticket.html:127 +#: models.py:531 templates/helpdesk/ticket.html:135 msgid "New Status" msgstr "Новый статус" -#: models.py:522 +#: models.py:535 msgid "If the status was changed, what was it changed to?" msgstr "Если статус был изменён, на что он был изменён?" -#: models.py:551 models.py:608 +#: models.py:542 models.py:566 models.py:628 msgid "Follow-up" msgstr "Наблюдение" -#: models.py:555 models.py:1236 +#: models.py:543 +msgid "Follow-ups" +msgstr "" + +#: models.py:570 models.py:1285 msgid "Field" msgstr "Поле" -#: models.py:560 +#: models.py:575 msgid "Old Value" msgstr "Старое значение" -#: models.py:566 +#: models.py:581 msgid "New Value" msgstr "Новое значение" -#: models.py:574 +#: models.py:589 msgid "removed" msgstr "удалённый" -#: models.py:576 +#: models.py:591 #, python-format msgid "set to %s" msgstr "установлен в %s" -#: models.py:578 +#: models.py:593 #, python-format msgid "changed from \"%(old_value)s\" to \"%(new_value)s\"" msgstr "изменён с \"%(old_value)s\" на \"%(new_value)s\"" -#: models.py:612 +#: models.py:600 +msgid "Ticket change" +msgstr "" + +#: models.py:601 +msgid "Ticket changes" +msgstr "" + +#: models.py:632 msgid "File" msgstr "Файл" -#: models.py:617 +#: models.py:637 msgid "Filename" msgstr "Имя файла" -#: models.py:622 +#: models.py:642 msgid "MIME Type" msgstr "MIME тип" -#: models.py:627 +#: models.py:647 msgid "Size" msgstr "Размер" -#: models.py:628 +#: models.py:648 msgid "Size of this file in bytes" msgstr "Размер этого файла в байтах" -#: models.py:663 +#: models.py:665 +msgid "Attachment" +msgstr "" + +#: models.py:666 +msgid "Attachments" +msgstr "" + +#: models.py:685 msgid "" "Leave blank to allow this reply to be used for all queues, or select those " "queues you wish to limit this reply to." msgstr "Оставьте пустым что бы позволить всем очередям использовать этот ответ, или выберете каким очередям можно использовать этот ответ." -#: models.py:668 models.py:709 models.py:1003 +#: models.py:690 models.py:733 models.py:1042 #: templates/helpdesk/email_ignore_list.html:13 msgid "Name" msgstr "Имя" -#: models.py:670 +#: models.py:692 msgid "" "Only used to assist users with selecting a reply - not shown to the user." msgstr "Используется пользователям только что бы помочь им выбрать ответ - пользователю не показывается." -#: models.py:675 +#: models.py:697 msgid "Body" msgstr "Тело" -#: models.py:676 +#: models.py:698 msgid "" "Context available: {{ ticket }} - ticket object (eg {{ ticket.title }}); {{ " "queue }} - The queue; and {{ user }} - the current user." msgstr "Доступный контекст: {{ ticket }} - тикет (например {{ ticket.title }}); {{ queue }} - очередь; и {{ user }} - текущий пользователь." -#: models.py:703 +#: models.py:705 +msgid "Pre-set reply" +msgstr "" + +#: models.py:706 +msgid "Pre-set replies" +msgstr "" + +#: models.py:727 msgid "" "Leave blank for this exclusion to be applied to all queues, or select those " "queues you wish to exclude with this entry." msgstr "Оставьте пустым что бы это исключение применялось ко всем очередям, или выберите очереди для который применять исключение." -#: models.py:715 +#: models.py:739 msgid "Date on which escalation should not happen" msgstr "Дата когда новые тикеты не должны подниматься." -#: models.py:732 +#: models.py:746 +msgid "Escalation exclusion" +msgstr "" + +#: models.py:747 +msgid "Escalation exclusions" +msgstr "" + +#: models.py:760 msgid "Template Name" msgstr "Имя шаблона" -#: models.py:737 +#: models.py:765 msgid "Subject" msgstr "Тема" -#: models.py:739 +#: models.py:767 msgid "" "This will be prefixed with \"[ticket.ticket] ticket.title\". We recommend " "something simple such as \"(Updated\") or \"(Closed)\" - the same context is" " available as in plain_text, below." msgstr "Добавится приставка \"[ticket.ticket] ticket.title\". Мы рекомендуем что нибудь простое например \"(Updated\") или \"(Closed)\" - тот же контекст доступен ниже в plain_text." -#: models.py:745 +#: models.py:773 msgid "Heading" msgstr "Заголовок" -#: models.py:747 +#: models.py:775 msgid "" "In HTML e-mails, this will be the heading at the top of the email - the same" " context is available as in plain_text, below." msgstr "В HTML электронных письмах, это будет в заголовке - тот же контекст доступен в виде plain_text ниже." -#: models.py:753 +#: models.py:781 msgid "Plain Text" msgstr "Чистый текст" -#: models.py:754 +#: models.py:782 msgid "" "The context available to you includes {{ ticket }}, {{ queue }}, and " "depending on the time of the call: {{ resolution }} or {{ comment }}." msgstr "Доступный контекст для включения {{ ticket }}, {{ queue }}, и в зависимости от времени вызова: {{ resolution }} или {{ comment }}." -#: models.py:760 +#: models.py:788 msgid "HTML" msgstr "HTML" -#: models.py:761 +#: models.py:789 msgid "The same context is available here as in plain_text, above." msgstr "Тот же самый контекст доступен здесь как в plain_text выше." -#: models.py:770 +#: models.py:798 msgid "Locale of this template." msgstr "Локаль этого шаблона." -#: models.py:817 templates/helpdesk/kb_index.html:10 -#: templates/helpdesk/public_homepage.html:10 +#: models.py:806 +msgid "e-mail template" +msgstr "" + +#: models.py:807 +msgid "e-mail templates" +msgstr "" + +#: models.py:834 +msgid "Knowledge base category" +msgstr "категорию Базы Знаний" + +#: models.py:835 +msgid "Knowledge base categories" +msgstr "Категории Базы Знаний" + +#: models.py:849 templates/helpdesk/kb_index.html:11 +#: templates/helpdesk/public_homepage.html:11 msgid "Category" msgstr "Категория" -#: models.py:826 +#: models.py:858 msgid "Question" msgstr "Вопрос" -#: models.py:830 +#: models.py:862 msgid "Answer" msgstr "Ответ" -#: models.py:834 +#: models.py:866 msgid "Votes" msgstr "Голоса" -#: models.py:835 +#: models.py:867 msgid "Total number of votes cast for this item" msgstr "Общее количество отданных голосов" -#: models.py:840 +#: models.py:872 msgid "Positive Votes" msgstr "Положительные голоса" -#: models.py:841 +#: models.py:873 msgid "Number of votes for this item which were POSITIVE." msgstr "Количество положительно проголосовавших." -#: models.py:846 +#: models.py:878 msgid "Last Updated" msgstr "Последний раз обновлялось" -#: models.py:847 +#: models.py:879 msgid "The date on which this question was most recently changed." msgstr "Дата когда этот вопрос был последний раз изменён." -#: models.py:861 +#: models.py:893 msgid "Unrated" msgstr "Неоценённый" -#: models.py:892 templates/helpdesk/ticket_list.html:158 +#: models.py:901 +msgid "Knowledge base item" +msgstr "" + +#: models.py:902 +msgid "Knowledge base items" +msgstr "" + +#: models.py:926 templates/helpdesk/ticket_list.html:170 msgid "Query Name" msgstr "Имя запроса" -#: models.py:894 +#: models.py:928 msgid "User-provided name for this query" msgstr "Имя запроса определённое пользователем" -#: models.py:898 +#: models.py:932 msgid "Shared With Other Users?" msgstr "Доступен остальным пользователям?" -#: models.py:901 +#: models.py:935 msgid "Should other users see this query?" msgstr "Виден ли этот запрос другим пользователям?" -#: models.py:905 +#: models.py:939 msgid "Search Query" msgstr "Поисковый запрос" -#: models.py:906 +#: models.py:940 msgid "Pickled query object. Be wary changing this." msgstr "Pickle-упакованные объекты запросов. Не изменяйте их." -#: models.py:927 +#: models.py:950 +msgid "Saved search" +msgstr "" + +#: models.py:951 +msgid "Saved searches" +msgstr "" + +#: models.py:966 msgid "Settings Dictionary" msgstr "Словарь настроек" -#: models.py:928 +#: models.py:967 msgid "" "This is a base64-encoded representation of a pickled Python dictionary. Do " "not change this field via the admin." msgstr "Это base64-кодированное представление pickle-упакованного Python словаря. Не изменяйте его через административный интерфейс." -#: models.py:997 +#: models.py:993 +msgid "User Setting" +msgstr "" + +#: models.py:994 templates/helpdesk/navigation.html:37 +#: templates/helpdesk/user_settings.html:6 +msgid "User Settings" +msgstr "Настройки пользователя" + +#: models.py:1036 msgid "" "Leave blank for this e-mail to be ignored on all queues, or select those " "queues you wish to ignore this e-mail for." msgstr "Оставьте пустым, чтобы этот адрес электронной почты был проигнорирован во всех очередях, или выберите те очереди, для которых он будет проигнорирован." -#: models.py:1009 +#: models.py:1048 msgid "Date on which this e-mail address was added" msgstr "Дата добавления этого адреса электронной почты" -#: models.py:1017 +#: models.py:1056 msgid "" "Enter a full e-mail address, or portions with wildcards, eg *@domain.com or " "postmaster@*." msgstr "Введите электронный адрес почты - полный или шаблон с подстановочными знаками, например, *@domain.com или postmaster@*." -#: models.py:1022 +#: models.py:1061 msgid "Save Emails in Mailbox?" msgstr "Сохранять сообщения в почтовом ящике?" -#: models.py:1025 +#: models.py:1064 msgid "" "Do you want to save emails from this address in the mailbox? If this is " "unticked, emails from this address will be deleted." msgstr "Хотите ли вы сохранить сообщения с этого адреса в почтовом ящике? Если убрать данную опцию, сообщения электронной почты с этого адреса будут удалены." -#: models.py:1080 +#: models.py:1101 +msgid "Ignored e-mail address" +msgstr "" + +#: models.py:1102 +msgid "Ignored e-mail addresses" +msgstr "" + +#: models.py:1124 msgid "User who wishes to receive updates for this ticket." msgstr "Пользователи желающие получать обновления для этого тикета" -#: models.py:1088 +#: models.py:1132 msgid "For non-user followers, enter their e-mail address" msgstr "Для незарегистрированных пользователей введите их электронные адреса почты" -#: models.py:1092 +#: models.py:1136 msgid "Can View Ticket?" msgstr "Может посмотреть тикет?" -#: models.py:1094 +#: models.py:1138 msgid "Can this CC login to view the ticket details?" msgstr "Может ли этот адрес из поля \"Копия\" войти, чтобы просмотреть тикет? " -#: models.py:1098 +#: models.py:1142 msgid "Can Update Ticket?" msgstr "Может изменить тикет?" -#: models.py:1100 +#: models.py:1144 msgid "Can this CC login and update the ticket?" msgstr "Может ли этот адрес из поля \"Копия\" войти и изменить тикет?" -#: models.py:1131 +#: models.py:1175 msgid "Field Name" msgstr "Название Поля" -#: models.py:1132 +#: models.py:1176 msgid "" "As used in the database and behind the scenes. Must be unique and consist of" " only lowercase letters with no punctuation." msgstr "При использовании в базе данных и за кулисами. Должно быть уникальным и состоять только из строчных латинских букв, без знаков препинания." -#: models.py:1137 +#: models.py:1181 msgid "Label" msgstr "Метка" -#: models.py:1139 +#: models.py:1183 msgid "The display label for this field" msgstr "Отображаемое название для этого поля" -#: models.py:1143 +#: models.py:1187 msgid "Help Text" msgstr "Текст подсказки" -#: models.py:1144 +#: models.py:1188 msgid "Shown to the user when editing the ticket" msgstr "Виден пользователю при редактировании тикета" -#: models.py:1150 +#: models.py:1194 msgid "Character (single line)" msgstr "Символьный (одна строчка)" -#: models.py:1151 +#: models.py:1195 msgid "Text (multi-line)" msgstr "Текстовый (много строк)" -#: models.py:1152 +#: models.py:1196 msgid "Integer" msgstr "Целочисленный" -#: models.py:1153 +#: models.py:1197 msgid "Decimal" msgstr "Вещественный" -#: models.py:1154 +#: models.py:1198 msgid "List" msgstr "Список" -#: models.py:1155 +#: models.py:1199 msgid "Boolean (checkbox yes/no)" msgstr "Boolean (флажок да / нет)" -#: models.py:1157 +#: models.py:1201 msgid "Time" msgstr "Время" -#: models.py:1158 +#: models.py:1202 msgid "Date & Time" msgstr "Дата и время" -#: models.py:1160 +#: models.py:1204 msgid "URL" msgstr "Ссылка" -#: models.py:1161 +#: models.py:1205 msgid "IP Address" msgstr "IP адрес" -#: models.py:1166 +#: models.py:1210 msgid "Data Type" msgstr "Тип данных" -#: models.py:1168 +#: models.py:1212 msgid "Allows you to restrict the data entered into this field" msgstr "Позволяет ограничить данные, введенные в это поле" -#: models.py:1173 +#: models.py:1217 msgid "Maximum Length (characters)" msgstr "Максимальная длина (символьный)" -#: models.py:1179 +#: models.py:1223 msgid "Decimal Places" msgstr "Число знаков после запятой" -#: models.py:1180 +#: models.py:1224 msgid "Only used for decimal fields" msgstr "Используется только для вещественных полей" -#: models.py:1186 +#: models.py:1230 msgid "Add empty first choice to List?" msgstr "Добавить пустое значение первым в список выбора?" -#: models.py:1187 +#: models.py:1232 msgid "" "Only for List: adds an empty first entry to the choices list, which enforces" " that the user makes an active choice." msgstr "Только для списка: Добавляет пустое значение первой записью в список выбора, который гарантирует, что пользователь точно сделает выбор." -#: models.py:1191 +#: models.py:1236 msgid "List Values" msgstr "Значения списка" -#: models.py:1192 +#: models.py:1237 msgid "For list fields only. Enter one option per line." msgstr "Только для полей списка. Вводите по одному значению на строку" -#: models.py:1198 +#: models.py:1243 msgid "Ordering" msgstr "Сортировка" -#: models.py:1199 +#: models.py:1244 msgid "Lower numbers are displayed first; higher numbers are listed later" msgstr "Более низкие числа отображаются сначала; более высокие значения перечислены позже" -#: models.py:1213 +#: models.py:1258 msgid "Required?" msgstr "Обязателен?" -#: models.py:1214 +#: models.py:1259 msgid "Does the user have to enter a value for this field?" msgstr "Обязательно ли вводить значение этого поля?" -#: models.py:1218 +#: models.py:1263 msgid "Staff Only?" msgstr "Только для персонала?" -#: models.py:1219 +#: models.py:1264 msgid "" "If this is ticked, then the public submission form will NOT show this field" msgstr "Если это отметить, то общедоступная форма представления не покажет этого поля" -#: models.py:1262 +#: models.py:1273 +msgid "Custom field" +msgstr "настраиваемое поле" + +#: models.py:1274 +msgid "Custom fields" +msgstr "Настраиваемые поля" + +#: models.py:1297 +msgid "Ticket custom field value" +msgstr "" + +#: models.py:1298 +msgid "Ticket custom field values" +msgstr "" + +#: models.py:1315 msgid "Depends On Ticket" msgstr "Зависит от талона" -#: management/commands/create_usersettings.py:21 +#: models.py:1324 +msgid "Ticket dependency" +msgstr "" + +#: models.py:1325 +msgid "Ticket dependencies" +msgstr "" + +#: management/commands/create_usersettings.py:25 msgid "" "Check for user without django-helpdesk UserSettings and create settings if " "required. Uses settings.DEFAULT_USER_SETTINGS which can be overridden to " "suit your situation." msgstr "Проверить пользователя без django-helpdesk UserSettings и создать настройки, если требуется. Используйте settings.DEFAULT_USER_SETTINGS в файле настройки, который может быть изменен в зависимости от ситуации." -#: management/commands/escalate_tickets.py:143 +#: management/commands/escalate_tickets.py:148 #, python-format msgid "Ticket escalated after %s days" msgstr "Тикет поднят после %s дней" -#: management/commands/get_email.py:151 +#: management/commands/get_email.py:158 msgid "Created from e-mail" msgstr "Создан из электронной почты" -#: management/commands/get_email.py:155 +#: management/commands/get_email.py:162 msgid "Unknown Sender" msgstr "Неизвестный отправитель" -#: management/commands/get_email.py:209 +#: management/commands/get_email.py:216 msgid "" "No plain-text email body available. Please see attachment " "email_html_body.html." msgstr "Доступно не текстовое тело электронного сообщения. Пожалуйста, посмотрите email_html_body.html." -#: management/commands/get_email.py:213 +#: management/commands/get_email.py:220 msgid "email_html_body.html" msgstr "email_html_body.html" -#: management/commands/get_email.py:256 +#: management/commands/get_email.py:263 #, python-format msgid "E-Mail Received from %(sender_email)s" msgstr "Электронное сообщение полученное от %(sender_email)s" -#: management/commands/get_email.py:264 +#: management/commands/get_email.py:271 #, python-format msgid "Ticket Re-Opened by E-Mail Received from %(sender_email)s" msgstr "Тикет заново открыт полученным от %(sender_email)s электронным сообщением" -#: management/commands/get_email.py:322 +#: management/commands/get_email.py:329 msgid " (Reopened)" msgstr " (Возобновлено)" -#: management/commands/get_email.py:324 +#: management/commands/get_email.py:331 msgid " (Updated)" msgstr "(Обновлено)" #: templates/helpdesk/attribution.html:2 msgid "" -"Powered by django-" -"helpdesk." -msgstr "Работает на django-helpdesk." +"django-helpdesk." +msgstr "" -#: templates/helpdesk/attribution.html:4 -msgid "For technical support please contact:" -msgstr "За технической поддержкой обращайтесь:" - -#: templates/helpdesk/base.html:9 +#: templates/helpdesk/base.html:10 msgid "Powered by django-helpdesk" msgstr "Работает на django-helpdesk" -#: templates/helpdesk/base.html:19 templates/helpdesk/rss_list.html:9 -#: templates/helpdesk/rss_list.html:23 templates/helpdesk/rss_list.html:28 +#: templates/helpdesk/base.html:20 templates/helpdesk/rss_list.html:9 +#: templates/helpdesk/rss_list.html:24 templates/helpdesk/rss_list.html:31 msgid "My Open Tickets" msgstr "Мои открытые тикеты" -#: templates/helpdesk/base.html:20 +#: templates/helpdesk/base.html:21 msgid "All Recent Activity" msgstr "Вся последняя активность" -#: templates/helpdesk/base.html:21 templates/helpdesk/dashboard.html:76 +#: templates/helpdesk/base.html:22 templates/helpdesk/dashboard.html:99 #: templates/helpdesk/rss_list.html:15 msgid "Unassigned Tickets" msgstr "Неназначенные тикеты" -#: templates/helpdesk/base.html:101 templates/helpdesk/public_base.html:6 -#: templates/helpdesk/public_base.html:14 +#: templates/helpdesk/base.html:52 templates/helpdesk/public_base.html:6 +#: templates/helpdesk/public_base.html:18 msgid "Helpdesk" msgstr "Помощь и поддержка" -#: templates/helpdesk/base.html:111 templates/helpdesk/rss_list.html:9 +#: templates/helpdesk/base.html:62 templates/helpdesk/rss_list.html:9 #: templates/helpdesk/rss_list.html:12 templates/helpdesk/rss_list.html:15 -#: templates/helpdesk/rss_list.html:27 templates/helpdesk/rss_list.html:28 +#: templates/helpdesk/rss_list.html:30 templates/helpdesk/rss_list.html:31 msgid "RSS Icon" msgstr "Иконка RSS" -#: templates/helpdesk/base.html:111 templates/helpdesk/rss_list.html:2 +#: templates/helpdesk/base.html:62 templates/helpdesk/rss_list.html:2 #: templates/helpdesk/rss_list.html.py:4 msgid "RSS Feeds" msgstr "RSS ленты новостей" -#: templates/helpdesk/base.html:112 +#: templates/helpdesk/base.html:63 msgid "API" msgstr "API" -#: templates/helpdesk/base.html:113 -msgid "User Settings" -msgstr "Настройки пользователя" - -#: templates/helpdesk/base.html:115 -msgid "Change Language" -msgstr "Измененить язык" - -#: templates/helpdesk/base.html:117 +#: templates/helpdesk/base.html:64 templates/helpdesk/system_settings.html:6 msgid "System Settings" msgstr "Системные настройки" #: templates/helpdesk/confirm_delete_saved_query.html:3 -#: templates/helpdesk/ticket_list.html:144 +#: templates/helpdesk/ticket_list.html:146 msgid "Delete Saved Query" msgstr "Удалить сохранный запрос" -#: templates/helpdesk/confirm_delete_saved_query.html:5 +#: templates/helpdesk/confirm_delete_saved_query.html:6 +msgid "Delete Query" +msgstr "" + +#: templates/helpdesk/confirm_delete_saved_query.html:8 #, python-format msgid "" -"\n" -"

Delete Query

\n" -"\n" -"

Are you sure you want to delete this saved filter (%(query_title)s)? To re-create it, you will need to manually re-filter your ticket listing.

\n" -msgstr "\n

Удалить запрос

\n\n

Вы уверены что вы хотите удалить сохранённый фильтр (%(query_title)s)? Что бы пересоздать его, вам придётся заново перефильтровать ваши тикеты из списка.

\n" +"Are you sure you want to delete this saved filter " +"(%(query_title)s)? To re-create it, you will need to manually re-" +"filter your ticket listing." +msgstr "" #: templates/helpdesk/confirm_delete_saved_query.html:11 -msgid "You have shared this query, so other users may be using it. If you delete it, they will have to manually create their own query." -msgstr "Вы поделились запросом, теперь остальные пользователи могут его использовать. Если вы удалите его, им придётся сделать себе собственный запрос." +msgid "" +"You have shared this query, so other users may be using it. If you delete " +"it, they will have to manually create their own query." +msgstr "" -#: templates/helpdesk/confirm_delete_saved_query.html:15 -#: templates/helpdesk/delete_ticket.html:11 +#: templates/helpdesk/confirm_delete_saved_query.html:14 +#: templates/helpdesk/delete_ticket.html:10 msgid "No, Don't Delete It" msgstr "Нет, не удалять" -#: templates/helpdesk/confirm_delete_saved_query.html:17 -#: templates/helpdesk/delete_ticket.html:13 +#: templates/helpdesk/confirm_delete_saved_query.html:16 +#: templates/helpdesk/delete_ticket.html:12 msgid "Yes - Delete It" msgstr "Удалить" @@ -1071,26 +1174,24 @@ msgid "Create Ticket" msgstr "Создать тикет" #: templates/helpdesk/create_ticket.html:10 -#: templates/helpdesk/public_homepage.html:39 +#: templates/helpdesk/navigation.html:65 templates/helpdesk/navigation.html:68 +#: templates/helpdesk/public_homepage.html:27 msgid "Submit a Ticket" -msgstr "Отправить тикет" +msgstr "Отправить талон" #: templates/helpdesk/create_ticket.html:11 +#: templates/helpdesk/edit_ticket.html:11 msgid "Unless otherwise stated, all fields are required." -msgstr "Все поля обязательны для заполнения пока не сказано обратное." +msgstr "" #: templates/helpdesk/create_ticket.html:11 +#: templates/helpdesk/edit_ticket.html:11 +#: templates/helpdesk/public_homepage.html:28 msgid "Please provide as descriptive a title and description as possible." -msgstr "Пожалуйста, напишите заголовок и описание как можно более точно отображающими суть проблемы." +msgstr "" -#: templates/helpdesk/create_ticket.html:17 -#: templates/helpdesk/edit_ticket.html:19 -#: templates/helpdesk/public_homepage.html:50 -msgid "(Optional)" -msgstr "(Опционально)" - -#: templates/helpdesk/create_ticket.html:26 -#: templates/helpdesk/public_homepage.html:59 +#: templates/helpdesk/create_ticket.html:30 +#: templates/helpdesk/public_homepage.html:55 msgid "Submit Ticket" msgstr "Отправить тикет" @@ -1098,131 +1199,176 @@ msgstr "Отправить тикет" msgid "Helpdesk Dashboard" msgstr "Панель управления Helpdesk" -#: templates/helpdesk/dashboard.html:10 -msgid "Helpdesk Summary" -msgstr "Сводка по Helpdesk" - -#: templates/helpdesk/dashboard.html:25 +#: templates/helpdesk/dashboard.html:9 msgid "" "Welcome to your Helpdesk Dashboard! From here you can quickly see tickets " "submitted by you, tickets you are working on, and those tickets that have no" " owner." msgstr "Добро пожаловать на вашу панель Helpdesk! Отсюда вы можете быстро увидеть ваши собственные тикеты, а также те, которые еще не имеют владельца." -#: templates/helpdesk/dashboard.html:27 -msgid "" -"Welcome to your Helpdesk Dashboard! From here you can quickly see your own " -"tickets, and those tickets that have no owner. Why not pick up an orphan " -"ticket and sort it out for a customer?" -msgstr "Добро пожаловать на вашу панель Helpdesk! Отсюда вы можете быстро увидеть ваши собственные тикеты, а также те, которые еще не имеют владельца. Почему бы не забрать новые и не обработать их?" +#: templates/helpdesk/dashboard.html:14 +msgid "Helpdesk Summary" +msgstr "Сводка по Helpdesk" #: templates/helpdesk/dashboard.html:36 +msgid "Current Ticket Stats" +msgstr "" + +#: templates/helpdesk/dashboard.html:37 +msgid "Average number of days until ticket is closed (all tickets): " +msgstr "Среднее число дней до закрытия тикета (все тикеты)" + +#: templates/helpdesk/dashboard.html:38 +msgid "" +"Average number of days until ticket is closed (tickets opened in last 60 " +"days): " +msgstr "Среднее число дней до закрытия тикета (за последние 60 дней)" + +#: templates/helpdesk/dashboard.html:39 +msgid "Click" +msgstr "Щелкните" + +#: templates/helpdesk/dashboard.html:39 +msgid "for detailed average by month." +msgstr "для детального отчета за месяц." + +#: templates/helpdesk/dashboard.html:40 +msgid "Distribution of open tickets, grouped by time period:" +msgstr "" + +#: templates/helpdesk/dashboard.html:41 +msgid "Days since opened" +msgstr "Дней с момента открытия" + +#: templates/helpdesk/dashboard.html:41 +msgid "Number of open tickets" +msgstr "Число открытых тикетов" + +#: templates/helpdesk/dashboard.html:57 msgid "All Tickets submitted by you" msgstr "Все тикеты, отправленные вами" -#: templates/helpdesk/dashboard.html:37 templates/helpdesk/dashboard.html:57 -#: templates/helpdesk/dashboard.html:77 templates/helpdesk/dashboard.html:99 -#: templates/helpdesk/ticket_list.html:199 +#: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 +#: templates/helpdesk/dashboard.html:100 templates/helpdesk/dashboard.html:124 +#: templates/helpdesk/ticket_list.html:225 msgid "Pr" msgstr "Приоритет" -#: templates/helpdesk/dashboard.html:37 templates/helpdesk/dashboard.html:57 -#: templates/helpdesk/dashboard.html:99 +#: templates/helpdesk/dashboard.html:58 templates/helpdesk/dashboard.html:78 +#: templates/helpdesk/dashboard.html:124 msgid "Last Update" msgstr "Последнее обновление" -#: templates/helpdesk/dashboard.html:56 +#: templates/helpdesk/dashboard.html:77 msgid "Open Tickets assigned to you (you are working on this ticket)" msgstr "Открыть тикеты, присвоенные Вам (вы работаете с этим тикетом)" -#: templates/helpdesk/dashboard.html:69 +#: templates/helpdesk/dashboard.html:92 msgid "You have no tickets assigned to you." -msgstr "Нет тикеты, назначенных вам." +msgstr "Нет тикетов, назначенных вам." -#: templates/helpdesk/dashboard.html:76 +#: templates/helpdesk/dashboard.html:99 msgid "(pick up a ticket if you start to work on it)" msgstr "(забрать тикет, если вы начинаете работать с ним)" -#: templates/helpdesk/dashboard.html:85 -#: templates/helpdesk/ticket_desc_table.html:22 +#: templates/helpdesk/dashboard.html:110 +#: templates/helpdesk/ticket_desc_table.html:38 msgid "Take" msgstr "Взять" -#: templates/helpdesk/dashboard.html:85 +#: templates/helpdesk/dashboard.html:110 #: templates/helpdesk/email_ignore_list.html:13 #: templates/helpdesk/email_ignore_list.html:23 #: templates/helpdesk/ticket_cc_list.html:15 #: templates/helpdesk/ticket_cc_list.html:23 -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Delete" msgstr "Удалить" -#: templates/helpdesk/dashboard.html:89 +#: templates/helpdesk/dashboard.html:114 msgid "There are no unassigned tickets." msgstr "Нет неназначенных тикетов." -#: templates/helpdesk/dashboard.html:98 +#: templates/helpdesk/dashboard.html:123 msgid "Closed & resolved Tickets you used to work on" msgstr "Закрыт и решены тикеты, связанные с вами" #: templates/helpdesk/delete_ticket.html:3 +#: templates/helpdesk/delete_ticket.html:6 msgid "Delete Ticket" msgstr "Удалить тикет" #: templates/helpdesk/delete_ticket.html:8 #, python-format -msgid "Are you sure you want to delete this ticket (%(ticket_title)s)? All traces of the ticket, including followups, attachments, and updates will be irreversibly removed." -msgstr "Вы уверены что хотите удалить этот тикет (%(ticket_title)s)? Все следы тикета, включая наблюдения, вложенные файлы и обновления будут безвозвратно удалены." +msgid "" +"Are you sure you want to delete this ticket (%(ticket_title)s)? All" +" traces of the ticket, including followups, attachments, and updates will be" +" irreversibly removed." +msgstr "" #: templates/helpdesk/edit_ticket.html:3 msgid "Edit Ticket" msgstr "Редактировать тикет" -#: templates/helpdesk/edit_ticket.html:6 +#: templates/helpdesk/edit_ticket.html:9 msgid "Edit a Ticket" -msgstr "Редактирование Тикета" +msgstr "Редактировать заявку" -#: templates/helpdesk/edit_ticket.html:6 +#: templates/helpdesk/edit_ticket.html:13 msgid "Note" -msgstr "Замечание" +msgstr "" -#: templates/helpdesk/edit_ticket.html:6 -msgid "Editing a ticket does not send an e-mail to the ticket owner or submitter. No new details should be entered, this form should only be used to fix incorrect details or clean up the submission." -msgstr "Редактирование тикета не отправляет сообщение по электронной почте владельцу или отправителю талона. Не добавляйте новых подробностей в талон. Эта форма только для исправления или уточнения проблемы." +#: templates/helpdesk/edit_ticket.html:13 +msgid "" +"Editing a ticket does not send an e-mail to the ticket owner or " +"submitter. No new details should be entered, this form should only be used " +"to fix incorrect details or clean up the submission." +msgstr "" -#: templates/helpdesk/edit_ticket.html:28 +#: templates/helpdesk/edit_ticket.html:33 msgid "Save Changes" msgstr "Сохранить изменения" #: templates/helpdesk/email_ignore_add.html:3 +#: templates/helpdesk/email_ignore_add.html:6 #: templates/helpdesk/email_ignore_add.html:23 msgid "Ignore E-Mail Address" msgstr "Игнорировать адрес электронной почты" -#: templates/helpdesk/email_ignore_add.html:5 -msgid "To ignore an e-mail address and prevent any emails from that address creating tickets automatically, enter the e-mail address below." -msgstr "Чтобы игнорировать адрес электронной почты, предотвратить автоматическое создание тикетов письмами с него, укажите его ниже." +#: templates/helpdesk/email_ignore_add.html:8 +msgid "" +"To ignore an e-mail address and prevent any emails from that address " +"creating tickets automatically, enter the e-mail address below." +msgstr "" -msgid "You can either enter a whole e-mail address such as email@domain.com or a portion of an e-mail address with a wildcard, such as *@domain.com or user@*." -msgstr "Вы можете указать как полный адрес, например, email@domain.com, так и его часть - с подстановочным знаком, например, *@domain.com или user@*." +#: templates/helpdesk/email_ignore_add.html:10 +msgid "" +"You can either enter a whole e-mail address such as " +"email@domain.com or a portion of an e-mail address with a wildcard," +" such as *@domain.com or user@*." +msgstr "" #: templates/helpdesk/email_ignore_del.html:3 msgid "Delete Ignored E-Mail Address" msgstr "Удалить игнорируемый адрес электронной почты" -#: templates/helpdesk/email_ignore_del.html:5 +#: templates/helpdesk/email_ignore_del.html:6 msgid "Un-Ignore E-Mail Address" -msgstr "Разблокировать адрес электронной почты" +msgstr "" +#: templates/helpdesk/email_ignore_del.html:8 #, python-format -msgid "Are you sure you wish to stop removing this email address (%(email_address)s) and allow their e-mails to automatically create tickets in your system? You can re-add this e-mail address at any time." -msgstr "Вы уверены что хотите разблокировать этот адрес электронной почты (%(email_address)s) и позволить сообщениям с этого адреса автоматически создавать тикеты в вашей системе? Вы можете добавить этот адрес электронной почты в любое время." +msgid "" +"Are you sure you wish to stop removing this email address " +"(%(email_address)s) and allow their e-mails to automatically create" +" tickets in your system? You can re-add this e-mail address at any time." +msgstr "" -#: templates/helpdesk/email_ignore_del.html:11 +#: templates/helpdesk/email_ignore_del.html:10 msgid "Keep Ignoring It" msgstr "Продолжать игнорировать" -#: templates/helpdesk/email_ignore_del.html:13 +#: templates/helpdesk/email_ignore_del.html:12 msgid "Stop Ignoring It" msgstr "Разблокировать, пусть присылает письма" @@ -1243,16 +1389,12 @@ msgstr "\n

Игнорируемые адреса электронной по msgid "Date Added" msgstr "Дата добавления" -#: templates/helpdesk/email_ignore_list.html:13 -msgid "Queues" -msgstr "Очереди" - #: templates/helpdesk/email_ignore_list.html:13 msgid "Keep in mailbox?" msgstr "Сохранять в почтовом ящике?" #: templates/helpdesk/email_ignore_list.html:21 -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "All" msgstr "Все" @@ -1287,7 +1429,7 @@ msgid "Comment:" msgstr "Комментарий" #: templates/helpdesk/kb_category.html:4 -#: templates/helpdesk/kb_category.html:11 +#: templates/helpdesk/kb_category.html:12 #, python-format msgid "Knowledgebase Category: %(kbcat)s" msgstr "Категория Базы Знаний: %(kbcat)s" @@ -1297,12 +1439,12 @@ msgstr "Категория Базы Знаний: %(kbcat)s" msgid "You are viewing all items in the %(kbcat)s category." msgstr "Вы просматриваете всё содержимое в категории %(kbcat)s." -#: templates/helpdesk/kb_category.html:12 +#: templates/helpdesk/kb_category.html:13 msgid "Article" msgstr "Статья" -#: templates/helpdesk/kb_index.html:4 templates/helpdesk/navigation.html:11 -#: templates/helpdesk/navigation.html:33 +#: templates/helpdesk/kb_index.html:4 templates/helpdesk/navigation.html:21 +#: templates/helpdesk/navigation.html:71 msgid "Knowledgebase" msgstr "База Знаний" @@ -1313,8 +1455,8 @@ msgid "" "your problem prior to opening a support ticket." msgstr "Мы перечислили ряд статей в Базе Знаний для вашего ознакомления по следующим категориям. Пожалуйста, проверьте до создания талона, что ваш случай не описан в какой-либо из этих статей." -#: templates/helpdesk/kb_index.html:9 -#: templates/helpdesk/public_homepage.html:9 +#: templates/helpdesk/kb_index.html:10 +#: templates/helpdesk/public_homepage.html:10 msgid "Knowledgebase Categories" msgstr "Категории Базы Знаний" @@ -1323,7 +1465,7 @@ msgstr "Категории Базы Знаний" msgid "Knowledgebase: %(item)s" msgstr "База Знаний: %(item)s" -#: templates/helpdesk/kb_item.html:13 +#: templates/helpdesk/kb_item.html:16 #, python-format msgid "" "View other %(category_title)s " @@ -1331,88 +1473,82 @@ msgid "" "articles." msgstr "Смотреть другие %(category_title)s статьи, или продолжить просмотр остальных статьей Базы Знаний." -#: templates/helpdesk/kb_item.html:15 +#: templates/helpdesk/kb_item.html:18 msgid "Feedback" msgstr "Обратная Связь" -#: templates/helpdesk/kb_item.html:17 +#: templates/helpdesk/kb_item.html:20 msgid "" "We give our users an opportunity to vote for items that they believe have " "helped them out, in order for us to better serve future customers. We would " "appreciate your feedback on this article. Did you find it useful?" msgstr "Мы предоставляем нашим пользователям возможность голосовать за статьи, которые по их мнению, способствовали им, с тем чтобы мы могли лучше обслуживать клиентов в будущем. Мы будем признательны за ваши отзывы на эту статью. Было ли это полезным?" -#: templates/helpdesk/kb_item.html:20 +#: templates/helpdesk/kb_item.html:23 msgid "This article was useful to me" msgstr "Эта статья была полезна для меня" -#: templates/helpdesk/kb_item.html:21 +#: templates/helpdesk/kb_item.html:24 msgid "This article was not useful to me" msgstr "Эта статья была бесполезна для меня" -#: templates/helpdesk/kb_item.html:24 +#: templates/helpdesk/kb_item.html:27 msgid "The results of voting by other readers of this article are below:" msgstr "Результаты голосования других прочитавших эту статью указаны ниже:" -#: templates/helpdesk/kb_item.html:27 +#: templates/helpdesk/kb_item.html:30 #, python-format msgid "Recommendations: %(recommendations)s" msgstr "Рекомендации: %(recommendations)s" -#: templates/helpdesk/kb_item.html:28 +#: templates/helpdesk/kb_item.html:31 #, python-format msgid "Votes: %(votes)s" msgstr "Голоса: %(votes)s" -#: templates/helpdesk/kb_item.html:29 +#: templates/helpdesk/kb_item.html:32 #, python-format msgid "Overall Rating: %(score)s" msgstr "Общий рейтинг: %(score)s" -#: templates/helpdesk/navigation.html:4 +#: templates/helpdesk/navigation.html:16 templates/helpdesk/navigation.html:64 msgid "Dashboard" msgstr "Панель" -#: templates/helpdesk/navigation.html:5 -#: templates/helpdesk/ticket_list.html:198 -msgid "Tickets" -msgstr "Тикеты" - -#: templates/helpdesk/navigation.html:6 +#: templates/helpdesk/navigation.html:18 msgid "New Ticket" msgstr "Новый Тикет" -#: templates/helpdesk/navigation.html:8 +#: templates/helpdesk/navigation.html:19 msgid "Stats" msgstr "Статистика" -#: templates/helpdesk/navigation.html:14 -#: templates/helpdesk/ticket_list.html:46 -msgid "Load Saved Query" -msgstr "Загрузить сохраненный запрос" +#: templates/helpdesk/navigation.html:24 +msgid "Saved Query" +msgstr "" -#: templates/helpdesk/navigation.html:25 templates/helpdesk/navigation.html:35 -msgid "Logout" -msgstr "Выход" +#: templates/helpdesk/navigation.html:39 +msgid "Change password" +msgstr "" -#: templates/helpdesk/navigation.html:26 +#: templates/helpdesk/navigation.html:50 msgid "Search..." msgstr "Поиск..." -#: templates/helpdesk/navigation.html:26 +#: templates/helpdesk/navigation.html:50 msgid "Enter a keyword, or a ticket number to jump straight to that ticket." msgstr "Введите ключевое слово или номер тикета, чтобы перейти прямо на этот тикет." -#: templates/helpdesk/navigation.html:31 -msgid "Submit A Ticket" -msgstr "Отправить тикет" +#: templates/helpdesk/navigation.html:73 +msgid "Logout" +msgstr "Выход" -#: templates/helpdesk/navigation.html:35 +#: templates/helpdesk/navigation.html:73 msgid "Log In" msgstr "Войти" #: templates/helpdesk/public_change_language.html:2 -#: templates/helpdesk/public_homepage.html:21 +#: templates/helpdesk/public_homepage.html:73 #: templates/helpdesk/public_view_form.html:4 #: templates/helpdesk/public_view_ticket.html:2 msgid "View a Ticket" @@ -1426,69 +1562,81 @@ msgstr "Изменение языка отображения" msgid "Knowledgebase Articles" msgstr "Категории Статей" -#: templates/helpdesk/public_homepage.html:29 +#: templates/helpdesk/public_homepage.html:28 +msgid "All fields are required." +msgstr "" + +#: templates/helpdesk/public_homepage.html:66 +msgid "Please use button at upper right to login first." +msgstr "Пожалуйста, используйте кнопку в правом верхнем углу для входа сначала." + +#: templates/helpdesk/public_homepage.html:82 #: templates/helpdesk/public_view_form.html:15 msgid "Your E-mail Address" msgstr "Ваш адрес электронной почты" -#: templates/helpdesk/public_homepage.html:33 +#: templates/helpdesk/public_homepage.html:86 #: templates/helpdesk/public_view_form.html:19 msgid "View Ticket" msgstr "Просмотреть талон" -#: templates/helpdesk/public_homepage.html:41 -msgid "All fields are required." -msgstr "Все поля являются обязательными для заполнения." - -#: templates/helpdesk/public_homepage.html:67 -msgid "Please use button at upper right to login first." -msgstr "Пожалуйста, используйте кнопку в правом верхнем углу для входа сначала." - #: templates/helpdesk/public_spam.html:4 msgid "Unable To Open Ticket" msgstr "Невозможно открыть тикет" -#: templates/helpdesk/public_spam.html:6 +#: templates/helpdesk/public_spam.html:5 msgid "Sorry, but there has been an error trying to submit your ticket." -msgstr "Извините, но произошла ошибка при попытке сохранить тикет." +msgstr "" -msgid "Our system has marked your submission as spam, so we are unable to save it. If this is not spam, please press back and re-type your message. Be careful to avoid sounding 'spammy', and if you have heaps of links please try removing them if possible." -msgstr "Наша система отметила ваше сообщение как спам, так что мы не можем его сохранить. Если это не спам, пожалуйста вернитесь назад и введите свое сообщение еще раз. Будьте осторожны, чтобы избежать похожести на \"спам\", и если у вас есть очень много ссылок, пожалуйста, попробуйте по возможности удалить их." +#: templates/helpdesk/public_spam.html:6 +msgid "" +"Our system has marked your submission as spam, so we are " +"unable to save it. If this is not spam, please press back and re-type your " +"message. Be careful to avoid sounding 'spammy', and if you have heaps of " +"links please try removing them if possible." +msgstr "" -msgid "We are sorry for any inconvenience, however this check is required to avoid our helpdesk resources being overloaded by spammers." -msgstr "Мы приносим извинения за возможные неудобства, однако эта проверка необходима, чтобы избежать растраты ресурсов на спамеров." +#: templates/helpdesk/public_spam.html:7 +msgid "" +"We are sorry for any inconvenience, however this check is required to avoid " +"our helpdesk resources being overloaded by spammers." +msgstr "" #: templates/helpdesk/public_view_form.html:8 msgid "Error:" msgstr "Ошибка:" -#: templates/helpdesk/public_view_ticket.html:8 +#: templates/helpdesk/public_view_ticket.html:9 #, python-format msgid "Queue: %(queue_name)s" msgstr "Очередь: %(queue_name)s" -#: templates/helpdesk/public_view_ticket.html:11 -#: templates/helpdesk/ticket_desc_table.html:16 +#: templates/helpdesk/public_view_ticket.html:13 +#: templates/helpdesk/ticket_desc_table.html:32 msgid "Submitted On" msgstr "Отправлен в" -#: templates/helpdesk/public_view_ticket.html:46 -#: templates/helpdesk/ticket_desc_table.html:74 +#: templates/helpdesk/public_view_ticket.html:35 +msgid "Tags" +msgstr "Тэги" + +#: templates/helpdesk/public_view_ticket.html:48 +#: templates/helpdesk/ticket_desc_table.html:26 msgid "Accept" msgstr "Принять" -#: templates/helpdesk/public_view_ticket.html:46 -#: templates/helpdesk/ticket_desc_table.html:74 +#: templates/helpdesk/public_view_ticket.html:48 +#: templates/helpdesk/ticket_desc_table.html:26 msgid "Accept and Close" msgstr "Принять и закрыть" -#: templates/helpdesk/public_view_ticket.html:55 -#: templates/helpdesk/ticket.html:64 +#: templates/helpdesk/public_view_ticket.html:57 +#: templates/helpdesk/ticket.html:66 msgid "Follow-Ups" msgstr "Наблюдения" -#: templates/helpdesk/public_view_ticket.html:63 -#: templates/helpdesk/ticket.html:92 +#: templates/helpdesk/public_view_ticket.html:65 +#: templates/helpdesk/ticket.html:100 #, python-format msgid "Changed %(field)s from %(old_value)s to %(new_value)s." msgstr "Изменено %(field)s с %(old_value)s на %(new_value)s." @@ -1531,6 +1679,10 @@ msgstr "по Месяцам" msgid "Reports By Queue" msgstr "Отчеты в разрезе Очередей" +#: templates/helpdesk/report_index.html:27 views/staff.py:1049 +msgid "Days until ticket closed by Month" +msgstr "" + #: templates/helpdesk/report_output.html:19 msgid "" "You can run this query on filtered data by using one of your saved queries." @@ -1588,15 +1740,15 @@ msgid "" "new tickets coming into that queue." msgstr "Эти ленты RSS позволят вам видеть сводку по вашим собственным или всем тикетам, для любой очереди. Например, если вы управляете персоналом, использующим определенную очередь, можно использовать ленту RSS для просмотра новых тикетов этой очереди." -#: templates/helpdesk/rss_list.html:22 +#: templates/helpdesk/rss_list.html:23 msgid "Per-Queue Feeds" msgstr "Ленты Новостей по Очередям" -#: templates/helpdesk/rss_list.html:23 +#: templates/helpdesk/rss_list.html:24 msgid "All Open Tickets" msgstr "Все открытые Тикеты" -#: templates/helpdesk/rss_list.html:27 +#: templates/helpdesk/rss_list.html:30 msgid "Open Tickets" msgstr "Открытые Тикеты" @@ -1604,8 +1756,9 @@ msgstr "Открытые Тикеты" msgid "Change System Settings" msgstr "Изменить системные настройки" +#: templates/helpdesk/system_settings.html:8 msgid "The following items can be maintained by you or other superusers:" -msgstr "Следующие задачи можете выполнить вы и другие суперпользователи:" +msgstr "" #: templates/helpdesk/system_settings.html:11 msgid "E-Mail Ignore list" @@ -1643,77 +1796,81 @@ msgstr "Просмотреть Тикет" msgid "Attach another File" msgstr "Прикрепить другой файл" -#: templates/helpdesk/ticket.html:34 templates/helpdesk/ticket.html.py:197 +#: templates/helpdesk/ticket.html:34 templates/helpdesk/ticket.html.py:200 msgid "Add Another File" msgstr "Добавить другой файл" -#: templates/helpdesk/ticket.html:71 templates/helpdesk/ticket.html.py:81 +#: templates/helpdesk/ticket.html:73 templates/helpdesk/ticket.html.py:86 msgid "Private" msgstr "Приватный" -#: templates/helpdesk/ticket.html:111 +#: templates/helpdesk/ticket.html:119 msgid "Respond to this ticket" msgstr "Ответить на этот тикет" -#: templates/helpdesk/ticket.html:118 +#: templates/helpdesk/ticket.html:126 msgid "Use a Pre-set Reply" msgstr "Использовать предопределённые ответы" -#: templates/helpdesk/ticket.html:120 +#: templates/helpdesk/ticket.html:126 templates/helpdesk/ticket.html.py:166 +msgid "(Optional)" +msgstr "(Опционально)" + +#: templates/helpdesk/ticket.html:128 msgid "" "Selecting a pre-set reply will over-write your comment below. You can then " "modify the pre-set reply to your liking before saving this update." msgstr "Выбор предопределенного ответа перезапишет ваш комментарий. После чего (до сохранения этого обновления) можно исправить предопределенный ответ по своему усмотрению." -#: templates/helpdesk/ticket.html:123 +#: templates/helpdesk/ticket.html:131 msgid "Comment / Resolution" msgstr "Комментарий / Решение" -#: templates/helpdesk/ticket.html:125 +#: templates/helpdesk/ticket.html:133 msgid "" "You can insert ticket and queue details in your message. For more " "information, see the context help page." msgstr "Вы можете вставить детали о талоне и очереди в ваше сообщение. Для дополнительной информации смотрите Страница помощи про Контекст." -#: templates/helpdesk/ticket.html:128 +#: templates/helpdesk/ticket.html:136 msgid "" "This ticket cannot be resolved or closed until the tickets it depends on are" " resolved." msgstr "Этот тикет не может быть разрешен или закрыт, пока не будут закрыты или решены талоны от которых он зависит." -#: templates/helpdesk/ticket.html:158 +#: templates/helpdesk/ticket.html:166 msgid "Is this update public?" msgstr "Это публичный тикет?" -#: templates/helpdesk/ticket.html:160 +#: templates/helpdesk/ticket.html:168 msgid "" "If this is public, the submitter will be e-mailed your comment or " "resolution." msgstr "Если это публичный, отправитель получит по электронной почте ваш комментарий или решение." -#: templates/helpdesk/ticket.html:164 +#: templates/helpdesk/ticket.html:172 msgid "Change Further Details »" msgstr "Изменить дополнительную информацию »" -#: templates/helpdesk/ticket.html:173 templates/helpdesk/ticket_list.html:55 -#: templates/helpdesk/ticket_list.html:87 -#: templates/helpdesk/ticket_list.html:199 +#: templates/helpdesk/ticket.html:181 templates/helpdesk/ticket_list.html:68 +#: templates/helpdesk/ticket_list.html:97 +#: templates/helpdesk/ticket_list.html:225 msgid "Owner" msgstr "Владелец" -#: templates/helpdesk/ticket.html:174 +#: templates/helpdesk/ticket.html:182 msgid "Unassign" msgstr "Не назначен" -#: templates/helpdesk/ticket.html:190 +#: templates/helpdesk/ticket.html:193 msgid "Attach File(s) »" msgstr "Прикрепить файл(ы) »" -#: templates/helpdesk/ticket.html:196 +#: templates/helpdesk/ticket.html:199 msgid "Attach a File" msgstr "Прикрепить файл" -#: templates/helpdesk/ticket.html:204 +#: templates/helpdesk/ticket.html:207 msgid "Update This Ticket" msgstr "Обновить этот тикет" @@ -1816,263 +1973,256 @@ msgid "" "

Are you sure you wish to remove the dependency on this ticket?

\n" msgstr "\n

Удалить зависимость тикета

\n\n

Вы уверены, что хотите удалить зависимость для этого талона?

\n" -#: templates/helpdesk/ticket_desc_table.html:11 +#: templates/helpdesk/ticket_desc_table.html:7 msgid "Unhold" msgstr "Снять с удержания" -#: templates/helpdesk/ticket_desc_table.html:11 +#: templates/helpdesk/ticket_desc_table.html:7 msgid "Hold" msgstr "Удерживать" -#: templates/helpdesk/ticket_desc_table.html:13 +#: templates/helpdesk/ticket_desc_table.html:9 #, python-format msgid "Queue: %(queue)s" msgstr "Очередь: %(queue)s" -#: templates/helpdesk/ticket_desc_table.html:21 +#: templates/helpdesk/ticket_desc_table.html:37 msgid "Assigned To" msgstr "Назначен " -#: templates/helpdesk/ticket_desc_table.html:27 +#: templates/helpdesk/ticket_desc_table.html:43 msgid "Ignore" msgstr "Игнорировать" -#: templates/helpdesk/ticket_desc_table.html:36 +#: templates/helpdesk/ticket_desc_table.html:52 msgid "Copies To" msgstr "Копии для" -#: templates/helpdesk/ticket_desc_table.html:37 +#: templates/helpdesk/ticket_desc_table.html:53 msgid "Manage" msgstr "Настроить" -#: templates/helpdesk/ticket_desc_table.html:37 +#: templates/helpdesk/ticket_desc_table.html:53 msgid "" "Click here to add / remove people who should receive an e-mail whenever this" " ticket is updated." msgstr "Нажмите здесь, чтобы добавить / удалить людей, которые должны получать сообщения электронной почты каждый раз, когда этот тикет обновляется." -#: templates/helpdesk/ticket_desc_table.html:48 +#: templates/helpdesk/ticket_desc_table.html:53 +msgid "Subscribe" +msgstr "" + +#: templates/helpdesk/ticket_desc_table.html:53 +msgid "" +"Click here to subscribe yourself to this ticket, if you want to receive an " +"e-mail whenever this ticket is updated." +msgstr "" + +#: templates/helpdesk/ticket_desc_table.html:57 msgid "Dependencies" msgstr "Зависимости" -#: templates/helpdesk/ticket_desc_table.html:50 +#: templates/helpdesk/ticket_desc_table.html:59 msgid "" "This ticket cannot be resolved until the following ticket(s) are resolved" msgstr "Этот тикет не может быть разрешен или закрыт, пока не будут закрыты или решены следующие тикеты" -#: templates/helpdesk/ticket_desc_table.html:51 +#: templates/helpdesk/ticket_desc_table.html:60 msgid "Remove Dependency" msgstr "Удалить зависимость" -#: templates/helpdesk/ticket_desc_table.html:54 +#: templates/helpdesk/ticket_desc_table.html:63 msgid "This ticket has no dependencies." msgstr "Этот тикет не имеет зависимостей." -#: templates/helpdesk/ticket_desc_table.html:56 +#: templates/helpdesk/ticket_desc_table.html:65 msgid "Add Dependency" msgstr "Добавить зависимость" -#: templates/helpdesk/ticket_desc_table.html:56 +#: templates/helpdesk/ticket_desc_table.html:65 msgid "" "Click on 'Add Dependency', if you want to make this ticket dependent on " "another ticket. A ticket may not be closed until all tickets it depends on " "are closed." msgstr "Нажмите на 'Добавить зависимость', если вы хотите сделать этот тикет зависимым от другого тикета. Тикет не может быть закрыт, пока не будут закрыты все тикеты, от которых он зависит." -#: templates/helpdesk/ticket_list.html:2 -msgid "Ticket Listing" -msgstr "Список Тикетов" - -#: templates/helpdesk/ticket_list.html:41 -msgid "Query Options" -msgstr "Параметры запроса" - -#: templates/helpdesk/ticket_list.html:43 -msgid "Save This Query" -msgstr "Сохранить этот запрос" - -#: templates/helpdesk/ticket_list.html:51 +#: templates/helpdesk/ticket_list.html:59 msgid "Change Query" msgstr "Изменить запрос" -#: templates/helpdesk/ticket_list.html:54 -#: templates/helpdesk/ticket_list.html:69 +#: templates/helpdesk/ticket_list.html:67 +#: templates/helpdesk/ticket_list.html:79 msgid "Sorting" msgstr "Сортировка" -#: templates/helpdesk/ticket_list.html:58 -#: templates/helpdesk/ticket_list.html:137 +#: templates/helpdesk/ticket_list.html:71 +#: templates/helpdesk/ticket_list.html:139 msgid "Keywords" msgstr "Ключевые слова" -#: templates/helpdesk/ticket_list.html:59 +#: templates/helpdesk/ticket_list.html:72 msgid "Date Range" msgstr "Диапазон дат" -#: templates/helpdesk/ticket_list.html:90 +#: templates/helpdesk/ticket_list.html:100 msgid "Reverse" msgstr "Реверс" -#: templates/helpdesk/ticket_list.html:92 +#: templates/helpdesk/ticket_list.html:102 msgid "Ordering applied to tickets" msgstr "Сортировка применяема к тикетам" -#: templates/helpdesk/ticket_list.html:97 +#: templates/helpdesk/ticket_list.html:107 msgid "Owner(s)" msgstr "Владелец(ы)" -#: templates/helpdesk/ticket_list.html:101 +#: templates/helpdesk/ticket_list.html:111 msgid "(ME)" msgstr "(МЕНЯ)" -#: templates/helpdesk/ticket_list.html:105 +#: templates/helpdesk/ticket_list.html:115 msgid "Ctrl-Click to select multiple options" msgstr "Нажмите Ctrl для выбора нескольких вариантов" -#: templates/helpdesk/ticket_list.html:110 +#: templates/helpdesk/ticket_list.html:120 msgid "Queue(s)" msgstr "Очередь(и)" -#: templates/helpdesk/ticket_list.html:111 -#: templates/helpdesk/ticket_list.html:117 -#: templates/helpdesk/ticket_list.html:131 +#: templates/helpdesk/ticket_list.html:121 +#: templates/helpdesk/ticket_list.html:127 msgid "Ctrl-click to select multiple options" msgstr "Нажмите Ctrl для выбора нескольких вариантов" -#: templates/helpdesk/ticket_list.html:116 +#: templates/helpdesk/ticket_list.html:126 msgid "Status(es)" msgstr "Статус(ы)" -#: templates/helpdesk/ticket_list.html:122 +#: templates/helpdesk/ticket_list.html:132 msgid "Date (From)" msgstr "Дата (с)" -#: templates/helpdesk/ticket_list.html:123 +#: templates/helpdesk/ticket_list.html:133 msgid "Date (To)" msgstr "Дата (по)" -#: templates/helpdesk/ticket_list.html:124 +#: templates/helpdesk/ticket_list.html:134 msgid "Use YYYY-MM-DD date format, eg 2011-05-29" msgstr "Использовать формат даты гггг-мм-дд, например 2011-05-29" -#: templates/helpdesk/ticket_list.html:130 -msgid "Tag(s)" -msgstr "Тэг(и)" - -#: templates/helpdesk/ticket_list.html:138 +#: templates/helpdesk/ticket_list.html:140 msgid "" "Keywords are case-insensitive, and will be looked for in the title, body and" " submitter fields." msgstr "Ключевые слова не зависят от регистра букв и будут искаться в полях заголовка, тексте и отправителях." -#: templates/helpdesk/ticket_list.html:142 +#: templates/helpdesk/ticket_list.html:144 msgid "Apply Filter" msgstr "Применить фильтр" -#: templates/helpdesk/ticket_list.html:144 +#: templates/helpdesk/ticket_list.html:146 #, python-format -msgid "You are currently viewing saved query %(query_name)s." -msgstr "Вы просматриваете сохраненный запрос %(query_name)s." +msgid "You are currently viewing saved query \"%(query_name)s\"." +msgstr "" -#: templates/helpdesk/ticket_list.html:147 +#: templates/helpdesk/ticket_list.html:149 #, python-format msgid "" "Run a report on this " "query to see stats and charts for the data listed below." msgstr "Выполнить отчет для этого запроса, чтобы просмотреть статистику и графики для данных, перечисленных ниже." -#: templates/helpdesk/ticket_list.html:154 -#: templates/helpdesk/ticket_list.html:169 +#: templates/helpdesk/ticket_list.html:162 +#: templates/helpdesk/ticket_list.html:181 msgid "Save Query" msgstr "Сохранить запрос" -#: templates/helpdesk/ticket_list.html:160 +#: templates/helpdesk/ticket_list.html:172 msgid "" "This name appears in the drop-down list of saved queries. If you share your " "query, other users will see this name, so choose something clear and " "descriptive!" msgstr "Это название появится в выпадающем списке сохраненных запросов. Если вы дадите доступ к своему запросу другим пользователям, они увидят это название, так что выберите что-нибудь четкое, информативное!" -#: templates/helpdesk/ticket_list.html:162 +#: templates/helpdesk/ticket_list.html:174 msgid "Shared?" msgstr "Общие?" -#: templates/helpdesk/ticket_list.html:163 +#: templates/helpdesk/ticket_list.html:175 msgid "Yes, share this query with other users." msgstr "Да, поделится этим запросом с другими пользователями." -#: templates/helpdesk/ticket_list.html:164 +#: templates/helpdesk/ticket_list.html:176 msgid "" "If you share this query, it will be visible by all other logged-in " "users." msgstr "Если вы поделитесь этим запросом, его смогут видеть все авторизированные пользователи." -#: templates/helpdesk/ticket_list.html:176 +#: templates/helpdesk/ticket_list.html:195 msgid "Use Saved Query" msgstr "Использовать сохранённый запрос" -#: templates/helpdesk/ticket_list.html:178 +#: templates/helpdesk/ticket_list.html:202 msgid "Query" msgstr "Запрос" -#: templates/helpdesk/ticket_list.html:183 +#: templates/helpdesk/ticket_list.html:207 msgid "Run Query" msgstr "Выполнить запрос" -#: templates/helpdesk/ticket_list.html:213 +#: templates/helpdesk/ticket_list.html:240 msgid "No Tickets Match Your Selection" -msgstr "Тикетов соответствующих вашему запросу не найдено" +msgstr "Тикетов, соответствующих вашему запросу, не найдено" -#: templates/helpdesk/ticket_list.html:219 +#: templates/helpdesk/ticket_list.html:247 msgid "Previous" msgstr "Предыдущий" -#: templates/helpdesk/ticket_list.html:223 +#: templates/helpdesk/ticket_list.html:251 #, python-format msgid "Page %(ticket_num)s of %(num_pages)s." msgstr "Страница %(ticket_num)s из %(num_pages)s." -#: templates/helpdesk/ticket_list.html:227 +#: templates/helpdesk/ticket_list.html:255 msgid "Next" msgstr "Следующая" -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "Select:" msgstr "Выбрать:" -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "None" msgstr "Ничего" -#: templates/helpdesk/ticket_list.html:232 +#: templates/helpdesk/ticket_list.html:260 msgid "Inverse" msgstr "Обратная" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "With Selected Tickets:" msgstr "С выбранными тикетами:" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Take (Assign to me)" msgstr "Принять (Связать со мной)" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Close" msgstr "Закрыть" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Close (Don't Send E-Mail)" msgstr "Закрыть (не отправлять E-Mail)" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Close (Send E-Mail)" msgstr "Закрыть (отправить E-Mail)" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Assign To" msgstr "Назначить" -#: templates/helpdesk/ticket_list.html:234 +#: templates/helpdesk/ticket_list.html:262 msgid "Nobody (Unassign)" msgstr "Никому (Несвязанные)" @@ -2080,13 +2230,15 @@ msgstr "Никому (Несвязанные)" msgid "Change User Settings" msgstr "Изменить Настройки Пользователя" -#: templates/helpdesk/user_settings.html:14 -msgid "Use the following options to change the way your helpdesk system works for you. These settings do not impact any other user." -msgstr "Используйте следующие параметры для изменения, как системы helpdesk бкдет работать для вас. Эти параметры не воздействия любого другого пользователя,." +#: templates/helpdesk/user_settings.html:8 +msgid "" +"Use the following options to change the way your helpdesk system works for " +"you. These settings do not impact any other user." +msgstr "" -#: templates/helpdesk/user_settings.html:29 +#: templates/helpdesk/user_settings.html:14 msgid "Save Options" -msgstr "Сохранить Опции" +msgstr "Сохранить настройки" #: templates/helpdesk/registration/logged_out.html:2 msgid "Logged Out" @@ -2105,116 +2257,101 @@ msgstr "\n

Выход произведён

\n\n

Спасибо что msgid "Helpdesk Login" msgstr "Вход в Helpdesk" -#: templates/helpdesk/registration/login.html:9 -#: templates/helpdesk/registration/login.html:21 -msgid "Login" -msgstr "Вход" - -#: templates/helpdesk/registration/login.html:11 -msgid "" -"To log in and begin responding to cases, simply enter your username and " -"password below." -msgstr "Войдите что бы иметь возможность отвечать на вопросы, для этого просто введите имя пользователя и пароль ниже." - #: templates/helpdesk/registration/login.html:14 +msgid "To log in simply enter your username and password below." +msgstr "" + +#: templates/helpdesk/registration/login.html:17 msgid "Your username and password didn't match. Please try again." msgstr "Введённые имя пользователя и пароль не подошли. Пожалуйста попробуйте ещё раз." -#: templates/helpdesk/registration/login.html:16 -msgid "Username" -msgstr "Имя Пользователя" +#: templates/helpdesk/registration/login.html:20 +msgid "Login" +msgstr "Вход" -#: templates/helpdesk/registration/login.html:18 -msgid "Password" -msgstr "Пароль" - -#: views/feeds.py:35 +#: views/feeds.py:39 #, python-format msgid "Helpdesk: Open Tickets in queue %(queue)s for %(username)s" msgstr "Helpdesk: открытые тикеты в очереди %(queue)s для %(username)s" -#: views/feeds.py:40 +#: views/feeds.py:44 #, python-format msgid "Helpdesk: Open Tickets for %(username)s" msgstr "Helpdesk: открытые тикеты для %(username)s" -#: views/feeds.py:46 +#: views/feeds.py:50 #, python-format msgid "Open and Reopened Tickets in queue %(queue)s for %(username)s" msgstr "Открытые и переоткрытые тикеты в очереди %(queue)s для %(username)s" -#: views/feeds.py:51 +#: views/feeds.py:55 #, python-format msgid "Open and Reopened Tickets for %(username)s" msgstr "Открытые и переоткрытые тикеты для %(username)s" -#: views/feeds.py:98 +#: views/feeds.py:102 msgid "Helpdesk: Unassigned Tickets" msgstr "Helpdesk: неназначенные тикеты" -#: views/feeds.py:99 +#: views/feeds.py:103 msgid "Unassigned Open and Reopened tickets" msgstr "Неназначенные открытые и переоткрытые тикеты" -#: views/feeds.py:124 +#: views/feeds.py:128 msgid "Helpdesk: Recent Followups" msgstr "Helpdesk: недавние дополнения" -#: views/feeds.py:125 +#: views/feeds.py:129 msgid "" "Recent FollowUps, such as e-mail replies, comments, attachments and " "resolutions" msgstr "Недавние дополнения, такие как ответы на электронную почту, комментарии, прикрепленные файлы и решения" -#: views/feeds.py:140 +#: views/feeds.py:144 #, python-format msgid "Helpdesk: Open Tickets in queue %(queue)s" msgstr "Helpdesk: открытые тикеты в очереди %(queue)s" -#: views/feeds.py:145 +#: views/feeds.py:149 #, python-format msgid "Open and Reopened Tickets in queue %(queue)s" msgstr "Открытые и переоткрытые тикеты в очереди %(queue)s" -#: views/public.py:91 +#: views/public.py:89 msgid "Invalid ticket ID or e-mail address. Please try again." msgstr "Неверный ID тикета или адрес электронной почты, Пожалуйста попробуйте ещё." -#: views/public.py:109 +#: views/public.py:107 msgid "Submitter accepted resolution and closed ticket" msgstr "Отправитель одобрил решение и закрыл тикет" -#: views/staff.py:218 +#: views/staff.py:235 msgid "Accepted resolution and closed ticket" msgstr "Принято решение и тикет закрыт" -#: views/staff.py:246 -msgid "Sorry, you need to login to do that." -msgstr "Извините, но вам необходимо войти, чтобы сделать это." - -#: views/staff.py:295 +#: views/staff.py:369 #, python-format msgid "Assigned to %(username)s" msgstr "Назначен на %(username)s" -#: views/staff.py:318 +#: views/staff.py:392 msgid "Updated" msgstr "Обновлено" -#: views/staff.py:496 +#: views/staff.py:577 #, python-format msgid "Assigned to %(username)s in bulk update" msgstr "Назначен на %(username)s при массовом обновлении" -#: views/staff.py:501 +#: views/staff.py:582 msgid "Unassigned in bulk update" msgstr "Нераспределен при массовом обновлении" -#: views/staff.py:506 views/staff.py:511 +#: views/staff.py:587 views/staff.py:592 msgid "Closed in bulk update" msgstr "Закрыт при массовом обновлении" -#: views/staff.py:732 +#: views/staff.py:806 msgid "" "

Note: Your keyword search is case sensitive because of " "your database. This means the search will not be accurate. " @@ -2224,86 +2361,38 @@ msgid "" "matching\">Django Documentation on string matching in SQLite." msgstr "

Замечание: ваш поиск по ключевым словам происходит с учетом регистра из-за вашей базы данных. Это означает, что поиск не будет точным. При переключении на другую систему баз данных, вы получите лучший поиск! Для получения дополнительной информации ознакомьтесь с Django документацией про сравнение строк в SQLite." -#: views/staff.py:843 +#: views/staff.py:910 msgid "Ticket taken off hold" msgstr "Удержание тикета снято" -#: views/staff.py:846 +#: views/staff.py:913 msgid "Ticket placed on hold" msgstr "Тикет удерживается" -#: views/staff.py:914 -msgid "Jan" -msgstr "Янв" - -#: views/staff.py:915 -msgid "Feb" -msgstr "Фев" - -#: views/staff.py:916 -msgid "Mar" -msgstr "Мар" - -#: views/staff.py:917 -msgid "Apr" -msgstr "Апр" - -#: views/staff.py:918 -msgid "May" -msgstr "Май" - -#: views/staff.py:919 -msgid "Jun" -msgstr "Июн" - -#: views/staff.py:920 -msgid "Jul" -msgstr "Июл" - -#: views/staff.py:921 -msgid "Aug" -msgstr "Авг" - -#: views/staff.py:922 -msgid "Sep" -msgstr "Сен" - -#: views/staff.py:923 -msgid "Oct" -msgstr "Окт" - -#: views/staff.py:924 -msgid "Nov" -msgstr "Ноя" - -#: views/staff.py:925 -msgid "Dec" -msgstr "Дек" - -#: views/staff.py:951 +#: views/staff.py:1007 msgid "User by Priority" msgstr "Пользователи по Приоритетам" -#: views/staff.py:957 +#: views/staff.py:1013 msgid "User by Queue" msgstr "Пользователи по Очередям" -#: views/staff.py:963 +#: views/staff.py:1019 msgid "User by Status" msgstr "Пользователи по Статусам" -#: views/staff.py:969 +#: views/staff.py:1025 msgid "User by Month" msgstr "Пользователи по Месяцам" -#: views/staff.py:975 +#: views/staff.py:1031 msgid "Queue by Priority" msgstr "Очереди по Приоритетам" -#: views/staff.py:981 +#: views/staff.py:1037 msgid "Queue by Status" msgstr "Очереди по Статусам" -#: views/staff.py:987 +#: views/staff.py:1043 msgid "Queue by Month" msgstr "Очереди по Месяцам" diff --git a/helpdesk/management/commands/create_escalation_exclusions.py b/helpdesk/management/commands/create_escalation_exclusions.py index 089e9b26..fcda257d 100644 --- a/helpdesk/management/commands/create_escalation_exclusions.py +++ b/helpdesk/management/commands/create_escalation_exclusions.py @@ -16,12 +16,12 @@ from optparse import make_option import sys from django.core.management.base import BaseCommand, CommandError -from django.db.models import Q from helpdesk.models import EscalationExclusion, Queue class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -43,11 +43,12 @@ class Command(BaseCommand): default=False, dest='escalate-verbosely', help='Display a list of dates excluded'), - ) + ) def handle(self, *args, **options): days = options['days'] - occurrences = options['occurrences'] + # optparse should already handle the `or 1` + occurrences = options['occurrences'] or 1 verbose = False queue_slugs = options['queues'] queues = [] @@ -55,8 +56,6 @@ class Command(BaseCommand): if options['escalate-verbosely']: verbose = True - # this should already be handled by optparse - if not occurrences: occurrences = 1 if not (days and occurrences): raise CommandError('One or more occurrences must be specified.') @@ -116,7 +115,6 @@ def usage(): print(" --verbose, -v: Display a list of dates excluded") - if __name__ == '__main__': # This script can be run from the command-line or via Django's manage.py. try: @@ -126,7 +124,7 @@ if __name__ == '__main__': sys.exit(2) days = None - occurrences = None + occurrences = 1 verbose = False queue_slugs = None queues = [] @@ -139,9 +137,8 @@ if __name__ == '__main__': if o in ('-q', '--queues'): queue_slugs = a if o in ('-o', '--occurrences'): - occurrences = int(a) + occurrences = int(a) or 1 - if not occurrences: occurrences = 1 if not (days and occurrences): usage() sys.exit(2) diff --git a/helpdesk/management/commands/create_queue_permissions.py b/helpdesk/management/commands/create_queue_permissions.py index 66118e75..50e980c3 100644 --- a/helpdesk/management/commands/create_queue_permissions.py +++ b/helpdesk/management/commands/create_queue_permissions.py @@ -25,6 +25,7 @@ from helpdesk.models import Queue class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -32,7 +33,7 @@ class Command(BaseCommand): make_option( '--queues', '-q', help='Queues to include (default: all). Use queue slugs'), - ) + ) def handle(self, *args, **options): queue_slugs = options['queues'] @@ -71,4 +72,3 @@ class Command(BaseCommand): ) except IntegrityError: self.stdout.write(" .. permission already existed, skipping") - diff --git a/helpdesk/management/commands/create_usersettings.py b/helpdesk/management/commands/create_usersettings.py index eafa6278..46280159 100644 --- a/helpdesk/management/commands/create_usersettings.py +++ b/helpdesk/management/commands/create_usersettings.py @@ -4,23 +4,22 @@ django-helpdesk - A Django powered ticket tracker for small enterprise. See LICENSE for details. -create_usersettings.py - Easy way to create helpdesk-specific settings for +create_usersettings.py - Easy way to create helpdesk-specific settings for users who don't yet have them. """ from django.utils.translation import ugettext as _ from django.core.management.base import BaseCommand -try: - from django.contrib.auth import get_user_model - User = get_user_model() -except ImportError: - from django.contrib.auth.models import User +from django.contrib.auth import get_user_model from helpdesk.models import UserSettings from helpdesk.settings import DEFAULT_USER_SETTINGS +User = get_user_model() + + class Command(BaseCommand): - "create_usersettings command" + """create_usersettings command""" help = _('Check for user without django-helpdesk UserSettings ' 'and create settings if required. Uses ' @@ -28,10 +27,7 @@ class Command(BaseCommand): 'suit your situation.') def handle(self, *args, **options): - "handle command line" + """handle command line""" for u in User.objects.all(): - try: - s = UserSettings.objects.get(user=u) - except UserSettings.DoesNotExist: - s = UserSettings(user=u, settings=DEFAULT_USER_SETTINGS) - s.save() + UserSettings.objects.get_or_create(user=u, + defaults={'settings': DEFAULT_USER_SETTINGS}) diff --git a/helpdesk/management/commands/escalate_tickets.py b/helpdesk/management/commands/escalate_tickets.py index 9212813b..b2788762 100644 --- a/helpdesk/management/commands/escalate_tickets.py +++ b/helpdesk/management/commands/escalate_tickets.py @@ -28,6 +28,7 @@ from helpdesk.lib import send_templated_mail, safe_template_context class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) @@ -40,7 +41,7 @@ class Command(BaseCommand): action='store_true', default=False, help='Display a list of dates excluded'), - ) + ) def handle(self, *args, **options): verbose = False @@ -56,7 +57,7 @@ class Command(BaseCommand): queue_set = queue_slugs.split(',') for queue in queue_set: try: - q = Queue.objects.get(slug__exact=queue) + Queue.objects.get(slug__exact=queue) except Queue.DoesNotExist: raise CommandError("Queue %s does not exist." % queue) queues.append(queue) @@ -82,24 +83,23 @@ def escalate_tickets(queues, verbose): days += 1 workdate = workdate + timedelta(days=1) - req_last_escl_date = date.today() - timedelta(days=days) if verbose: print("Processing: %s" % q) for t in q.ticket_set.filter( - Q(status=Ticket.OPEN_STATUS) - | Q(status=Ticket.REOPENED_STATUS) - ).exclude( - priority=1 - ).filter( - Q(on_hold__isnull=True) - | Q(on_hold=False) - ).filter( - Q(last_escalation__lte=req_last_escl_date) - | Q(last_escalation__isnull=True, created__lte=req_last_escl_date) - ): + Q(status=Ticket.OPEN_STATUS) | + Q(status=Ticket.REOPENED_STATUS) + ).exclude( + priority=1 + ).filter( + Q(on_hold__isnull=True) | + Q(on_hold=False) + ).filter( + Q(last_escalation__lte=req_last_escl_date) | + Q(last_escalation__isnull=True, created__lte=req_last_escl_date) + ): t.last_escalation = timezone.now() t.priority -= 1 @@ -114,7 +114,7 @@ def escalate_tickets(queues, verbose): recipients=t.submitter_email, sender=t.queue.from_address, fail_silently=True, - ) + ) if t.queue.updated_ticket_cc: send_templated_mail( @@ -123,7 +123,7 @@ def escalate_tickets(queues, verbose): recipients=t.queue.updated_ticket_cc, sender=t.queue.from_address, fail_silently=True, - ) + ) if t.assigned_to: send_templated_mail( @@ -132,19 +132,19 @@ def escalate_tickets(queues, verbose): recipients=t.assigned_to.email, sender=t.queue.from_address, fail_silently=True, - ) + ) if verbose: print(" - Esclating %s from %s>%s" % ( t.ticket, - t.priority+1, + t.priority + 1, t.priority - ) + ) ) f = FollowUp( - ticket = t, - title = 'Ticket Escalated', + ticket=t, + title='Ticket Escalated', date=timezone.now(), public=True, comment=_('Ticket escalated after %s days' % q.escalate_days), @@ -152,10 +152,10 @@ def escalate_tickets(queues, verbose): f.save() tc = TicketChange( - followup = f, - field = _('Priority'), - old_value = t.priority + 1, - new_value = t.priority, + followup=f, + field=_('Priority'), + old_value=t.priority + 1, + new_value=t.priority, ) tc.save() diff --git a/helpdesk/management/commands/get_email.py b/helpdesk/management/commands/get_email.py index 99f45f73..a79e7619 100644 --- a/helpdesk/management/commands/get_email.py +++ b/helpdesk/management/commands/get_email.py @@ -5,11 +5,11 @@ Jutda Helpdesk - A Django powered ticket tracker for small enterprise. (c) Copyright 2008 Jutda. All Rights Reserved. See LICENSE for details. scripts/get_email.py - Designed to be run from cron, this script checks the - POP and IMAP boxes defined for the queues within a + POP and IMAP boxes, or a local mailbox directory, + defined for the queues within a helpdesk, creating tickets from the new messages (or adding to existing tickets if needed) """ -from __future__ import print_function import email import imaplib @@ -17,6 +17,8 @@ import mimetypes import poplib import re import socket +from os import listdir, unlink +from os.path import isfile, join from datetime import timedelta from email.header import decode_header @@ -25,10 +27,12 @@ from optparse import make_option from email_reply_parser import EmailReplyParser +from django import VERSION from django.core.files.base import ContentFile from django.core.management.base import BaseCommand from django.db.models import Q from django.utils.translation import ugettext as _ +from django.utils import six from helpdesk import settings try: @@ -39,20 +43,46 @@ except ImportError: from helpdesk.lib import send_templated_mail, safe_template_context from helpdesk.models import Queue, Ticket, FollowUp, Attachment, IgnoreEmail +import logging +from time import ctime + + +STRIPPED_SUBJECT_STRINGS = [ + "Re: ", + "Fw: ", + "RE: ", + "FW: ", + "Automatic reply: ", +] + class Command(BaseCommand): + def __init__(self): BaseCommand.__init__(self) - self.option_list += ( + # Django 1.7 uses different way to specify options than 1.8+ + if VERSION < (1, 8): + self.option_list += ( make_option( - '--quiet', '-q', + '--quiet', default=False, action='store_true', + dest='quiet', help='Hide details about each queue/message as they are processed'), - ) + ) - help = 'Process Jutda Helpdesk queues and process e-mails via POP3/IMAP as required, feeding them into the helpdesk.' + help = 'Process django-helpdesk queues and process e-mails via POP3/IMAP or ' \ + 'from a local mailbox directory as required, feeding them into the helpdesk.' + + def add_arguments(self, parser): + parser.add_argument( + '--quiet', + action='store_true', + dest='quiet', + default=False, + help='Hide details about each queue/message as they are processed', + ) def handle(self, *args, **options): quiet = options.get('quiet', False) @@ -64,118 +94,205 @@ def process_email(quiet=False): email_box_type__isnull=False, allow_email_submission=True): + logger = logging.getLogger('django.helpdesk.queue.' + q.slug) + if not q.logging_type or q.logging_type == 'none': + logging.disable(logging.CRITICAL) #disable all messages + elif q.logging_type == 'info': + logger.setLevel(logging.INFO) + elif q.logging_type == 'warn': + logger.setLevel(logging.WARN) + elif q.logging_type == 'error': + logger.setLevel(logging.ERROR) + elif q.logging_type == 'crit': + logger.setLevel(logging.CRITICAL) + elif q.logging_type == 'debug': + logger.setLevel(logging.DEBUG) + if quiet: + logger.propagate = False # do not propagate to root logger that would log to console + logdir = q.logging_dir or '/var/log/helpdesk/' + handler = logging.FileHandler(logdir + q.slug + '_get_email.log') + logger.addHandler(handler) + if not q.email_box_last_check: - q.email_box_last_check = timezone.now()-timedelta(minutes=30) + q.email_box_last_check = timezone.now() - timedelta(minutes=30) if not q.email_box_interval: q.email_box_interval = 0 - queue_time_delta = timedelta(minutes=q.email_box_interval) if (q.email_box_last_check + queue_time_delta) > timezone.now(): continue - process_queue(q, quiet=quiet) + process_queue(q, logger=logger) q.email_box_last_check = timezone.now() q.save() -def process_queue(q, quiet=False): - if not quiet: - print("Processing: %s" % q) +def process_queue(q, logger): + logger.info("***** %s: Begin processing mail for django-helpdesk" % ctime()) if q.socks_proxy_type and q.socks_proxy_host and q.socks_proxy_port: try: import socks except ImportError: - raise ImportError("Queue has been configured with proxy settings, but no socks library was installed. Try to install PySocks via pypi.") + no_socks_msg = "Queue has been configured with proxy settings, but no socks " \ + "library was installed. Try to install PySocks via PyPI." + logger.error(no_socks_msg) + raise ImportError(no_socks_msg) proxy_type = { 'socks4': socks.SOCKS4, 'socks5': socks.SOCKS5, }.get(q.socks_proxy_type) - socks.set_default_proxy(proxy_type=proxy_type, addr=q.socks_proxy_host, port=q.socks_proxy_port) + socks.set_default_proxy(proxy_type=proxy_type, + addr=q.socks_proxy_host, + port=q.socks_proxy_port) socket.socket = socks.socksocket else: - socket.socket = socket._socketobject + if six.PY2: + socket.socket = socket._socketobject + elif six.PY3: + import _socket + socket.socket = _socket.socket - email_box_type = settings.QUEUE_EMAIL_BOX_TYPE if settings.QUEUE_EMAIL_BOX_TYPE else q.email_box_type + email_box_type = settings.QUEUE_EMAIL_BOX_TYPE or q.email_box_type if email_box_type == 'pop3': - if q.email_box_ssl or settings.QUEUE_EMAIL_BOX_SSL: - if not q.email_box_port: q.email_box_port = 995 - server = poplib.POP3_SSL(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port)) + if not q.email_box_port: + q.email_box_port = 995 + server = poplib.POP3_SSL(q.email_box_host or + settings.QUEUE_EMAIL_BOX_HOST, + int(q.email_box_port)) else: - if not q.email_box_port: q.email_box_port = 110 - server = poplib.POP3(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port)) + if not q.email_box_port: + q.email_box_port = 110 + server = poplib.POP3(q.email_box_host or + settings.QUEUE_EMAIL_BOX_HOST, + int(q.email_box_port)) + + logger.info("Attempting POP3 server login") server.getwelcome() server.user(q.email_box_user or settings.QUEUE_EMAIL_BOX_USER) server.pass_(q.email_box_pass or settings.QUEUE_EMAIL_BOX_PASSWORD) - messagesInfo = server.list()[1] + logger.info("Received %s messages from POP3 server" % str(len(messagesInfo))) for msg in messagesInfo: msgNum = msg.split(" ")[0] - msgSize = msg.split(" ")[1] + logger.info("Processing message %s" % str(msgNum)) full_message = "\n".join(server.retr(msgNum)[1]) - ticket = ticket_from_message(message=full_message, queue=q, quiet=quiet) + ticket = ticket_from_message(message=full_message, queue=q) if ticket: server.dele(msgNum) + logger.info("Successfully processed message %s, deleted from POP3 server" % str(msgNum)) + else: + logger.warn("Message %s was not successfully processed, and will be left on POP3 server" % str(msgNum)) server.quit() elif email_box_type == 'imap': if q.email_box_ssl or settings.QUEUE_EMAIL_BOX_SSL: - if not q.email_box_port: q.email_box_port = 993 - server = imaplib.IMAP4_SSL(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port)) + if not q.email_box_port: + q.email_box_port = 993 + server = imaplib.IMAP4_SSL(q.email_box_host or + settings.QUEUE_EMAIL_BOX_HOST, + int(q.email_box_port)) else: - if not q.email_box_port: q.email_box_port = 143 - server = imaplib.IMAP4(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port)) + if not q.email_box_port: + q.email_box_port = 143 + server = imaplib.IMAP4(q.email_box_host or + settings.QUEUE_EMAIL_BOX_HOST, + int(q.email_box_port)) - server.login(q.email_box_user or settings.QUEUE_EMAIL_BOX_USER, q.email_box_pass or settings.QUEUE_EMAIL_BOX_PASSWORD) + logger.info("Attempting IMAP server login") + + server.login(q.email_box_user or + settings.QUEUE_EMAIL_BOX_USER, + q.email_box_pass or + settings.QUEUE_EMAIL_BOX_PASSWORD) server.select(q.email_box_imap_folder) status, data = server.search(None, 'NOT', 'DELETED') if data: msgnums = data[0].split() + logger.info("Received %s messages from IMAP server" % str(len(msgnums))) for num in msgnums: + logger.info("Processing message %s" % str(num)) status, data = server.fetch(num, '(RFC822)') - ticket = ticket_from_message(message=data[0][1], queue=q, quiet=quiet) + ticket = ticket_from_message(message=data[0][1], queue=q) if ticket: server.store(num, '+FLAGS', '\\Deleted') - + logger.info("Successfully processed message %s, deleted from IMAP server" % str(msgNum)) + else: + logger.warn("Message %s was not successfully processed, and will be left on IMAP server" % str(msgNum)) + server.expunge() server.close() server.logout() + elif email_box_type == 'local': + mail_dir = q.email_box_local_dir or '/var/lib/mail/helpdesk/' + mail = [join(mail_dir, f) for f in listdir(mail_dir) if isfile(join(mail_dir, f))] + logger.info("Found %s messages in local mailbox directory" % str(len(mail))) + for m in mail: + logger.info("Processing message %s" % str(m)) + f = open(m, 'r') + ticket = ticket_from_message(message=f.read(), queue=q, logger=logger) + if ticket: + logger.info("Successfully processed message %s, ticket/comment created." % str(m)) + try: + #unlink(m) #delete message file if ticket was successful + logger.info("Successfully deleted message %s." % str(m)) + except: + logger.error("Unable to delete message %s." % str(m)) + else: + logger.warn("Message %s was not successfully processed, and will be left in local directory" % str(m)) + def decodeUnknown(charset, string): - if not charset: - try: - return string.decode('utf-8','ignore') - except: - return string.decode('iso8859-1','ignore') - return unicode(string, charset) + if six.PY2: + if not charset: + try: + return string.decode('utf-8', 'ignore') + except: + return string.decode('iso8859-1', 'ignore') + return unicode(string, charset) + elif six.PY3: + if type(string) is not str: + if not charset: + try: + return str(string, encoding='utf-8', errors='replace') + except: + return str(string, encoding='iso8859-1', errors='replace') + return str(string, encoding=charset) + return string + def decode_mail_headers(string): decoded = decode_header(string) - return u' '.join([unicode(msg, charset or 'utf-8') for msg, charset in decoded]) + if six.PY2: + return u' '.join([unicode(msg, charset or 'utf-8') for msg, charset in decoded]) + elif six.PY3: + return u' '.join([str(msg,encoding=charset,errors='replace') if charset else str(msg) for msg, charset in decoded]) -def ticket_from_message(message, queue, quiet): + +def ticket_from_message(message, queue, logger): # 'message' must be an RFC822 formatted message. msg = message message = email.message_from_string(msg) subject = message.get('subject', _('Created from e-mail')) subject = decode_mail_headers(decodeUnknown(message.get_charset(), subject)) - subject = subject.replace("Re: ", "").replace("Fw: ", "").replace("RE: ", "").replace("FW: ", "").replace("Automatic reply: ", "").strip() + for affix in STRIPPED_SUBJECT_STRINGS: + subject = subject.replace(affix, "") + subject = subject.strip() sender = message.get('from', _('Unknown Sender')) sender = decode_mail_headers(decodeUnknown(message.get_charset(), sender)) @@ -192,11 +309,13 @@ def ticket_from_message(message, queue, quiet): return False return True - matchobj = re.match(r".*\["+queue.slug+"-(?P\d+)\]", subject) + matchobj = re.match(r".*\[" + queue.slug + "-(?P\d+)\]", subject) if matchobj: # This is a reply or forward. ticket = matchobj.group('id') + logger.info("Matched tracking ID %s-%s" % (queue.slug, ticket)) else: + logger.info("No tracking ID matched.") ticket = None counter = 0 @@ -210,11 +329,14 @@ def ticket_from_message(message, queue, quiet): if name: name = collapse_rfc2231_value(name) - if part.get_content_maintype() == 'text' and name == None: + if part.get_content_maintype() == 'text' and name is None: if part.get_content_subtype() == 'plain': - body_plain = EmailReplyParser.parse_reply(decodeUnknown(part.get_content_charset(), part.get_payload(decode=True))) + body_plain = EmailReplyParser.parse_reply( + decodeUnknown(part.get_content_charset(), part.get_payload(decode=True))) + logger.debug("Discovered plain text MIME part") else: body_html = part.get_payload(decode=True) + logger.debug("Discovered HTML MIME part") else: if not name: ext = mimetypes.guess_extension(part.get_content_type()) @@ -224,14 +346,15 @@ def ticket_from_message(message, queue, quiet): 'filename': name, 'content': part.get_payload(decode=True), 'type': part.get_content_type()}, - ) + ) + logger.debug("Found MIME attachment %s" % name) counter += 1 if body_plain: body = body_plain else: - body = _('No plain-text email body available. Please see attachment email_html_body.html.') + body = _('No plain-text email body available. Please see attachment "email_html_body.html".') if body_html: files.append({ @@ -246,7 +369,9 @@ def ticket_from_message(message, queue, quiet): try: t = Ticket.objects.get(id=ticket) new = False + logger.info("Found existing ticket with Tracking ID %s-%s" % (t.queue.slug, t.id)) except Ticket.DoesNotExist: + logger.info("Tracking ID %s-%s not associated with existing ticket. Creating new ticket." % (queue.slug, ticket)) ticket = None priority = 3 @@ -259,7 +384,7 @@ def ticket_from_message(message, queue, quiet): if smtp_priority in high_priority_types or smtp_importance in high_priority_types: priority = 2 - if ticket == None: + if ticket is None: t = Ticket( title=subject, queue=queue, @@ -270,44 +395,49 @@ def ticket_from_message(message, queue, quiet): ) t.save() new = True - update = '' + logger.debug("Created new ticket %s-%s" % (t.queue.slug, t.id)) elif t.status == Ticket.CLOSED_STATUS: t.status = Ticket.REOPENED_STATUS t.save() f = FollowUp( - ticket = t, - title = _('E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}), - date = timezone.now(), - public = True, - comment = body, + ticket=t, + title=_('E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}), + date=timezone.now(), + public=True, + comment=body, ) if t.status == Ticket.REOPENED_STATUS: f.new_status = Ticket.REOPENED_STATUS f.title = _('Ticket Re-Opened by E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}) - - f.save() - if not quiet: - print((" [%s-%s] %s" % (t.queue.slug, t.id, t.title,)).encode('ascii', 'replace')) + f.save() + logger.debug("Created new FollowUp for Ticket") + + if six.PY2: + logger.info(("[%s-%s] %s" % (t.queue.slug, t.id, t.title,)).encode('ascii', 'replace')) + elif six.PY3: + logger.info("[%s-%s] %s" % (t.queue.slug, t.id, t.title,)) for file in files: if file['content']: - filename = file['filename'].encode('ascii', 'replace').replace(' ', '_') + if six.PY2: + filename = file['filename'].encode('ascii', 'replace').replace(' ', '_') + elif six.PY3: + filename = file['filename'].replace(' ', '_') filename = re.sub('[^a-zA-Z0-9._-]+', '', filename) + logger.info("Found attachment '%s'" % filename) a = Attachment( followup=f, filename=filename, mime_type=file['type'], size=len(file['content']), - ) + ) a.file.save(filename, ContentFile(file['content']), save=False) a.save() - if not quiet: - print(" - %s" % filename) - + logger.info("Attachment '%s' successfully added to ticket." % filename) context = safe_template_context(t) @@ -320,7 +450,7 @@ def ticket_from_message(message, queue, quiet): recipients=sender_email, sender=queue.from_address, fail_silently=True, - ) + ) if queue.new_ticket_cc: send_templated_mail( @@ -329,7 +459,7 @@ def ticket_from_message(message, queue, quiet): recipients=queue.new_ticket_cc, sender=queue.from_address, fail_silently=True, - ) + ) if queue.updated_ticket_cc and queue.updated_ticket_cc != queue.new_ticket_cc: send_templated_mail( @@ -338,15 +468,15 @@ def ticket_from_message(message, queue, quiet): recipients=queue.updated_ticket_cc, sender=queue.from_address, fail_silently=True, - ) + ) else: context.update(comment=f.comment) - if t.status == Ticket.REOPENED_STATUS: - update = _(' (Reopened)') - else: - update = _(' (Updated)') + # if t.status == Ticket.REOPENED_STATUS: + # update = _(' (Reopened)') + # else: + # update = _(' (Updated)') if t.assigned_to: send_templated_mail( @@ -355,7 +485,7 @@ def ticket_from_message(message, queue, quiet): recipients=t.assigned_to.email, sender=queue.from_address, fail_silently=True, - ) + ) if queue.updated_ticket_cc: send_templated_mail( @@ -364,11 +494,10 @@ def ticket_from_message(message, queue, quiet): recipients=queue.updated_ticket_cc, sender=queue.from_address, fail_silently=True, - ) + ) return t if __name__ == '__main__': process_email() - diff --git a/helpdesk/migrations/0003_initial_data_import.py b/helpdesk/migrations/0003_initial_data_import.py index 566993e0..cc478377 100644 --- a/helpdesk/migrations/0003_initial_data_import.py +++ b/helpdesk/migrations/0003_initial_data_import.py @@ -25,7 +25,7 @@ def load_fixture(apps, schema_editor): def unload_fixture(apps, schema_editor): - "Delete all EmailTemplate objects" + """Delete all EmailTemplate objects""" objects = deserialize_fixture() diff --git a/helpdesk/migrations/0013_email_box_local_dir_and_logging.py b/helpdesk/migrations/0013_email_box_local_dir_and_logging.py new file mode 100644 index 00000000..71ba784e --- /dev/null +++ b/helpdesk/migrations/0013_email_box_local_dir_and_logging.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-09-14 23:47 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('helpdesk', '0012_queue_default_owner'), + ] + + operations = [ + migrations.AddField( + model_name='queue', + name='email_box_local_dir', + field=models.CharField(blank=True, help_text='If using a local directory, what directory path do you wish to poll for new email? Example: /var/lib/mail/helpdesk/', max_length=200, null=True, verbose_name='E-Mail Local Directory'), + ), + migrations.AddField( + model_name='queue', + name='logging_dir', + field=models.CharField(blank=True, help_text='If logging is enabled, what directory should we use to store log files for this queue? If no directory is set, default to /var/log/helpdesk/', max_length=200, null=True, verbose_name='Logging Directory'), + ), + migrations.AddField( + model_name='queue', + name='logging_type', + field=models.CharField(blank=True, choices=[('none', 'None'), ('debug', 'Debug'), ('info', 'Information'), ('warn', 'Warning'), ('error', 'Error'), ('crit', 'Critical')], help_text='Set the default logging level. All messages at that level or above will be logged to the directory set below. If no level is set, logging will be disabled.', max_length=5, null=True, verbose_name='Logging Type'), + ), + migrations.AlterField( + model_name='queue', + name='email_box_type', + field=models.CharField(blank=True, choices=[('pop3', 'POP 3'), ('imap', 'IMAP'), ('local', 'Local Directory')], help_text='E-Mail server type for creating tickets automatically from a mailbox - both POP3 and IMAP are supported, as well as reading from a local directory.', max_length=5, null=True, verbose_name='E-Mail Box Type'), + ), + ] diff --git a/helpdesk/models.py b/helpdesk/models.py index 9ac917b6..8d34ff11 100644 --- a/helpdesk/models.py +++ b/helpdesk/models.py @@ -12,14 +12,10 @@ from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.db import models -from django.contrib.auth import get_user_model from django.conf import settings from django.utils.translation import ugettext_lazy as _, ugettext -from django import VERSION from django.utils.encoding import python_2_unicode_compatible -from helpdesk import settings as helpdesk_settings - try: from django.utils import timezone except ImportError: @@ -40,56 +36,56 @@ class Queue(models.Model): title = models.CharField( _('Title'), max_length=100, - ) + ) slug = models.SlugField( _('Slug'), max_length=50, unique=True, help_text=_('This slug is used when building ticket ID\'s. Once set, ' - 'try not to change it or e-mailing may get messy.'), - ) + 'try not to change it or e-mailing may get messy.'), + ) email_address = models.EmailField( _('E-Mail Address'), blank=True, null=True, help_text=_('All outgoing e-mails for this queue will use this e-mail ' - 'address. If you use IMAP or POP3, this should be the e-mail ' - 'address for that mailbox.'), - ) + 'address. If you use IMAP or POP3, this should be the e-mail ' + 'address for that mailbox.'), + ) locale = models.CharField( _('Locale'), max_length=10, blank=True, null=True, - help_text=_('Locale of this queue. All correspondence in this queue will be in this language.'), - ) + help_text=_('Locale of this queue. All correspondence in this ' + 'queue will be in this language.'), + ) allow_public_submission = models.BooleanField( _('Allow Public Submission?'), blank=True, default=False, - help_text=_('Should this queue be listed on the public submission ' - 'form?'), - ) + help_text=_('Should this queue be listed on the public submission form?'), + ) allow_email_submission = models.BooleanField( _('Allow E-Mail Submission?'), blank=True, default=False, help_text=_('Do you want to poll the e-mail box below for new ' - 'tickets?'), - ) + 'tickets?'), + ) escalate_days = models.IntegerField( _('Escalation Days'), blank=True, null=True, help_text=_('For tickets which are not held, how often do you wish to ' - 'increase their priority? Set to 0 for no escalation.'), - ) + 'increase their priority? Set to 0 for no escalation.'), + ) new_ticket_cc = models.CharField( _('New Ticket CC Address'), @@ -97,9 +93,9 @@ class Queue(models.Model): null=True, max_length=200, help_text=_('If an e-mail address is entered here, then it will ' - 'receive notification of all new tickets created for this queue. ' - 'Enter a comma between multiple e-mail addresses.'), - ) + 'receive notification of all new tickets created for this queue. ' + 'Enter a comma between multiple e-mail addresses.'), + ) updated_ticket_cc = models.CharField( _('Updated Ticket CC Address'), @@ -107,20 +103,21 @@ class Queue(models.Model): null=True, max_length=200, help_text=_('If an e-mail address is entered here, then it will ' - 'receive notification of all activity (new tickets, closed ' - 'tickets, updates, reassignments, etc) for this queue. Separate ' - 'multiple addresses with a comma.'), - ) + 'receive notification of all activity (new tickets, closed ' + 'tickets, updates, reassignments, etc) for this queue. Separate ' + 'multiple addresses with a comma.'), + ) email_box_type = models.CharField( _('E-Mail Box Type'), max_length=5, - choices=(('pop3', _('POP 3')), ('imap', _('IMAP'))), + choices=(('pop3', _('POP 3')), ('imap', _('IMAP')), ('local',_('Local Directory'))), blank=True, null=True, help_text=_('E-Mail server type for creating tickets automatically ' - 'from a mailbox - both POP3 and IMAP are supported.'), - ) + 'from a mailbox - both POP3 and IMAP are supported, as well as ' + 'reading from a local directory.'), + ) email_box_host = models.CharField( _('E-Mail Hostname'), @@ -128,25 +125,25 @@ class Queue(models.Model): blank=True, null=True, help_text=_('Your e-mail server address - either the domain name or ' - 'IP address. May be "localhost".'), - ) + 'IP address. May be "localhost".'), + ) email_box_port = models.IntegerField( _('E-Mail Port'), blank=True, null=True, help_text=_('Port number to use for accessing e-mail. Default for ' - 'POP3 is "110", and for IMAP is "143". This may differ on some ' - 'servers. Leave it blank to use the defaults.'), - ) + 'POP3 is "110", and for IMAP is "143". This may differ on some ' + 'servers. Leave it blank to use the defaults.'), + ) email_box_ssl = models.BooleanField( _('Use SSL for E-Mail?'), blank=True, default=False, help_text=_('Whether to use SSL for IMAP or POP3 - the default ports ' - 'when using SSL are 993 for IMAP and 995 for POP3.'), - ) + 'when using SSL are 993 for IMAP and 995 for POP3.'), + ) email_box_user = models.CharField( _('E-Mail Username'), @@ -154,7 +151,7 @@ class Queue(models.Model): blank=True, null=True, help_text=_('Username for accessing this mailbox.'), - ) + ) email_box_pass = models.CharField( _('E-Mail Password'), @@ -162,7 +159,7 @@ class Queue(models.Model): blank=True, null=True, help_text=_('Password for the above username'), - ) + ) email_box_imap_folder = models.CharField( _('IMAP Folder'), @@ -170,9 +167,18 @@ class Queue(models.Model): blank=True, null=True, help_text=_('If using IMAP, what folder do you wish to fetch messages ' - 'from? This allows you to use one IMAP account for multiple ' - 'queues, by filtering messages on your IMAP server into separate ' - 'folders. Default: INBOX.'), + 'from? This allows you to use one IMAP account for multiple ' + 'queues, by filtering messages on your IMAP server into separate ' + 'folders. Default: INBOX.'), + ) + + email_box_local_dir = models.CharField( + _('E-Mail Local Directory'), + max_length=200, + blank=True, + null=True, + help_text=_('If using a local directory, what directory path do you ' + 'wish to poll for new email? Example: /var/lib/mail/helpdesk/'), ) permission_name = models.CharField( @@ -182,8 +188,7 @@ class Queue(models.Model): null=True, editable=False, help_text=_('Name used in the django.contrib.auth permission system'), - ) - + ) email_box_interval = models.IntegerField( _('E-Mail Check Interval'), @@ -191,14 +196,14 @@ class Queue(models.Model): blank=True, null=True, default='5', - ) + ) email_box_last_check = models.DateTimeField( blank=True, null=True, editable=False, # This is updated by management/commands/get_mail.py. - ) + ) socks_proxy_type = models.CharField( _('Socks Proxy Type'), @@ -223,6 +228,27 @@ class Queue(models.Model): help_text=_('Socks proxy port number. Default: 9150 (default TOR port)'), ) + logging_type = models.CharField( + _('Logging Type'), + max_length=5, + choices=(('none', _('None')), ('debug', _('Debug')), ('info',_('Information')), ('warn', _('Warning')), ('error', _('Error')), ('crit', _('Critical'))), + blank=True, + null=True, + help_text=_('Set the default logging level. All messages at that ' + 'level or above will be logged to the directory set below. ' + 'If no level is set, logging will be disabled.'), + ) + + logging_dir = models.CharField( + _('Logging Directory'), + max_length=200, + blank=True, + null=True, + help_text=_('If logging is enabled, what directory should we use to ' + 'store log files for this queue? ' + 'If no directory is set, default to /var/log/helpdesk/'), + ) + default_owner = models.ForeignKey( settings.AUTH_USER_MODEL, related_name='default_owner', @@ -351,32 +377,32 @@ class Ticket(models.Model): title = models.CharField( _('Title'), max_length=200, - ) + ) queue = models.ForeignKey( Queue, verbose_name=_('Queue'), - ) + ) created = models.DateTimeField( _('Created'), blank=True, help_text=_('Date this ticket was first created'), - ) + ) modified = models.DateTimeField( _('Modified'), blank=True, help_text=_('Date this ticket was most recently changed.'), - ) + ) submitter_email = models.EmailField( _('Submitter E-Mail'), blank=True, null=True, help_text=_('The submitter will receive an email for all public ' - 'follow-ups left for this task.'), - ) + 'follow-ups left for this task.'), + ) assigned_to = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -384,35 +410,34 @@ class Ticket(models.Model): blank=True, null=True, verbose_name=_('Assigned to'), - ) + ) status = models.IntegerField( _('Status'), choices=STATUS_CHOICES, default=OPEN_STATUS, - ) + ) on_hold = models.BooleanField( _('On Hold'), blank=True, default=False, - help_text=_('If a ticket is on hold, it will not automatically be ' - 'escalated.'), - ) + help_text=_('If a ticket is on hold, it will not automatically be escalated.'), + ) description = models.TextField( _('Description'), blank=True, null=True, help_text=_('The content of the customers query.'), - ) + ) resolution = models.TextField( _('Resolution'), blank=True, null=True, help_text=_('The resolution provided to the customer by our staff.'), - ) + ) priority = models.IntegerField( _('Priority'), @@ -420,21 +445,21 @@ class Ticket(models.Model): default=3, blank=3, help_text=_('1 = Highest Priority, 5 = Low Priority'), - ) + ) due_date = models.DateTimeField( _('Due on'), blank=True, null=True, - ) + ) last_escalation = models.DateTimeField( blank=True, null=True, editable=False, help_text=_('The date this ticket was last escalated - updated ' - 'automatically by management/commands/escalate_tickets.py.'), - ) + 'automatically by management/commands/escalate_tickets.py.'), + ) def _get_assigned_to(self): """ Custom property to allow us to easily print 'Unassigned' if a @@ -453,7 +478,7 @@ class Ticket(models.Model): """ A user-friendly ticket ID, which is a combination of ticket ID and queue slug. This is generally used in e-mail subjects. """ - return u"[%s]" % (self.ticket_for_url) + return u"[%s]" % self.ticket_for_url ticket = property(_get_ticket) def _get_ticket_for_url(self): @@ -480,9 +505,11 @@ class Ticket(models.Model): Displays the ticket status, with an "On Hold" message if needed. """ held_msg = '' - if self.on_hold: held_msg = _(' - On Hold') + if self.on_hold: + held_msg = _(' - On Hold') dep_msg = '' - if self.can_be_resolved == False: dep_msg = _(' - Open dependencies') + if not self.can_be_resolved: + dep_msg = _(' - Open dependencies') return u'%s%s%s' % (self.get_status_display(), held_msg, dep_msg) get_status = property(_get_status) @@ -499,10 +526,10 @@ class Ticket(models.Model): site = Site(domain='configure-django-sites.com') return u"http://%s%s?ticket=%s&email=%s" % ( site.domain, - reverse('helpdesk_public_view'), + reverse('helpdesk:public_view'), self.ticket_for_url, self.submitter_email - ) + ) ticket_url = property(_get_ticket_url) def _get_staff_url(self): @@ -518,9 +545,9 @@ class Ticket(models.Model): site = Site(domain='configure-django-sites.com') return u"http://%s%s" % ( site.domain, - reverse('helpdesk_view', - args=[self.id]) - ) + reverse('helpdesk:view', + args=[self.id]) + ) staff_url = property(_get_staff_url) def _can_be_resolved(self): @@ -530,7 +557,8 @@ class Ticket(models.Model): False = There are non-resolved dependencies """ OPEN_STATUSES = (Ticket.OPEN_STATUS, Ticket.REOPENED_STATUS) - return TicketDependency.objects.filter(ticket=self).filter(depends_on__status__in=OPEN_STATUSES).count() == 0 + return TicketDependency.objects.filter(ticket=self).filter( + depends_on__status__in=OPEN_STATUSES).count() == 0 can_be_resolved = property(_can_be_resolved) class Meta: @@ -543,7 +571,7 @@ class Ticket(models.Model): return '%s %s' % (self.id, self.title) def get_absolute_url(self): - return ('helpdesk_view', (self.id,)) + return 'helpdesk:view', (self.id,) get_absolute_url = models.permalink(get_absolute_url) def save(self, *args, **kwargs): @@ -558,8 +586,8 @@ class Ticket(models.Model): super(Ticket, self).save(*args, **kwargs) - @classmethod - def queue_and_id_from_query(klass, query): + @staticmethod + def queue_and_id_from_query(query): # Apply the opposite logic here compared to self._get_ticket_for_url # Ensure that queues with '-' in them will work parts = query.split('-') @@ -568,6 +596,7 @@ class Ticket(models.Model): class FollowUpManager(models.Manager): + def private_followups(self): return self.filter(public=False) @@ -592,40 +621,40 @@ class FollowUp(models.Model): ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), - ) + ) date = models.DateTimeField( _('Date'), - default = timezone.now - ) + default=timezone.now + ) title = models.CharField( _('Title'), max_length=200, blank=True, null=True, - ) + ) comment = models.TextField( _('Comment'), blank=True, null=True, - ) + ) public = models.BooleanField( _('Public'), blank=True, default=False, help_text=_('Public tickets are viewable by the submitter and all ' - 'staff, but non-public tickets can only be seen by staff.'), - ) + 'staff, but non-public tickets can only be seen by staff.'), + ) user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=_('User'), - ) + ) new_status = models.IntegerField( _('New Status'), @@ -633,12 +662,12 @@ class FollowUp(models.Model): blank=True, null=True, help_text=_('If the status was changed, what was it changed to?'), - ) + ) objects = FollowUpManager() class Meta: - ordering = ['date'] + ordering = ('date',) verbose_name = _('Follow-up') verbose_name_plural = _('Follow-ups') @@ -665,24 +694,24 @@ class TicketChange(models.Model): followup = models.ForeignKey( FollowUp, verbose_name=_('Follow-up'), - ) + ) field = models.CharField( _('Field'), max_length=100, - ) + ) old_value = models.TextField( _('Old Value'), blank=True, null=True, - ) + ) new_value = models.TextField( _('New Value'), blank=True, null=True, - ) + ) def __str__(self): out = '%s ' % self.field @@ -694,7 +723,7 @@ class TicketChange(models.Model): out += ugettext('changed from "%(old_value)s" to "%(new_value)s"') % { 'old_value': self.old_value, 'new_value': self.new_value - } + } return out class Meta: @@ -710,7 +739,7 @@ def attachment_path(instance, filename): import os from django.conf import settings os.umask(0) - path = 'helpdesk/attachments/%s/%s' % (instance.followup.ticket.ticket_for_url, instance.followup.id ) + path = 'helpdesk/attachments/%s/%s' % (instance.followup.ticket.ticket_for_url, instance.followup.id) att_path = os.path.join(settings.MEDIA_ROOT, path) if settings.DEFAULT_FILE_STORAGE == "django.core.files.storage.FileSystemStorage": if not os.path.exists(att_path): @@ -728,28 +757,28 @@ class Attachment(models.Model): followup = models.ForeignKey( FollowUp, verbose_name=_('Follow-up'), - ) + ) file = models.FileField( _('File'), upload_to=attachment_path, max_length=1000, - ) + ) filename = models.CharField( _('Filename'), max_length=1000, - ) + ) mime_type = models.CharField( _('MIME Type'), max_length=255, - ) + ) size = models.IntegerField( _('Size'), help_text=_('Size of this file in bytes'), - ) + ) def get_upload_to(self, field_attname): """ Get upload_to path specific to this item """ @@ -758,13 +787,13 @@ class Attachment(models.Model): return u'helpdesk/attachments/%s/%s' % ( self.followup.ticket.ticket_for_url, self.followup.id - ) + ) def __str__(self): return '%s' % self.filename class Meta: - ordering = ['filename',] + ordering = ('filename',) verbose_name = _('Attachment') verbose_name_plural = _('Attachments') @@ -781,32 +810,31 @@ class PreSetReply(models.Model): When replying to a ticket, the user can select any reply set for the current queue, and the body text is fetched via AJAX. """ + class Meta: + ordering = ('name',) + verbose_name = _('Pre-set reply') + verbose_name_plural = _('Pre-set replies') queues = models.ManyToManyField( Queue, blank=True, help_text=_('Leave blank to allow this reply to be used for all ' - 'queues, or select those queues you wish to limit this reply to.'), - ) + 'queues, or select those queues you wish to limit this reply to.'), + ) name = models.CharField( _('Name'), max_length=100, help_text=_('Only used to assist users with selecting a reply - not ' - 'shown to the user.'), - ) + 'shown to the user.'), + ) body = models.TextField( _('Body'), help_text=_('Context available: {{ ticket }} - ticket object (eg ' - '{{ ticket.title }}); {{ queue }} - The queue; and {{ user }} ' - '- the current user.'), - ) - - class Meta: - ordering = ['name',] - verbose_name = _('Pre-set reply') - verbose_name_plural = _('Pre-set replies') + '{{ ticket.title }}); {{ queue }} - The queue; and {{ user }} ' + '- the current user.'), + ) def __str__(self): return '%s' % self.name @@ -827,20 +855,19 @@ class EscalationExclusion(models.Model): queues = models.ManyToManyField( Queue, blank=True, - help_text=_('Leave blank for this exclusion to be applied to all ' - 'queues, or select those queues you wish to exclude with this ' - 'entry.'), - ) + help_text=_('Leave blank for this exclusion to be applied to all queues, ' + 'or select those queues you wish to exclude with this entry.'), + ) name = models.CharField( _('Name'), max_length=100, - ) + ) date = models.DateField( _('Date'), help_text=_('Date on which escalation should not happen'), - ) + ) def __str__(self): return '%s' % self.name @@ -863,36 +890,35 @@ class EmailTemplate(models.Model): template_name = models.CharField( _('Template Name'), max_length=100, - ) + ) subject = models.CharField( _('Subject'), max_length=100, help_text=_('This will be prefixed with "[ticket.ticket] ticket.title"' - '. We recommend something simple such as "(Updated") or "(Closed)"' - ' - the same context is available as in plain_text, below.'), - ) + '. We recommend something simple such as "(Updated") or "(Closed)"' + ' - the same context is available as in plain_text, below.'), + ) heading = models.CharField( _('Heading'), max_length=100, help_text=_('In HTML e-mails, this will be the heading at the top of ' - 'the email - the same context is available as in plain_text, ' - 'below.'), - ) + 'the email - the same context is available as in plain_text, ' + 'below.'), + ) plain_text = models.TextField( _('Plain Text'), help_text=_('The context available to you includes {{ ticket }}, ' - '{{ queue }}, and depending on the time of the call: ' - '{{ resolution }} or {{ comment }}.'), - ) + '{{ queue }}, and depending on the time of the call: ' + '{{ resolution }} or {{ comment }}.'), + ) html = models.TextField( _('HTML'), - help_text=_('The same context is available here as in plain_text, ' - 'above.'), - ) + help_text=_('The same context is available here as in plain_text, above.'), + ) locale = models.CharField( _('Locale'), @@ -900,13 +926,13 @@ class EmailTemplate(models.Model): blank=True, null=True, help_text=_('Locale of this template.'), - ) + ) def __str__(self): return '%s' % self.template_name class Meta: - ordering = ['template_name', 'locale'] + ordering = ('template_name', 'locale') verbose_name = _('e-mail template') verbose_name_plural = _('e-mail templates') @@ -921,26 +947,26 @@ class KBCategory(models.Model): title = models.CharField( _('Title'), max_length=100, - ) + ) slug = models.SlugField( _('Slug'), - ) + ) description = models.TextField( _('Description'), - ) + ) def __str__(self): return '%s' % self.title class Meta: - ordering = ['title',] + ordering = ('title',) verbose_name = _('Knowledge base category') verbose_name_plural = _('Knowledge base categories') def get_absolute_url(self): - return ('helpdesk_kb_category', (), {'slug': self.slug}) + return 'kb_category', (), {'slug': self.slug} get_absolute_url = models.permalink(get_absolute_url) @@ -953,39 +979,38 @@ class KBItem(models.Model): category = models.ForeignKey( KBCategory, verbose_name=_('Category'), - ) + ) title = models.CharField( _('Title'), max_length=100, - ) + ) question = models.TextField( _('Question'), - ) + ) answer = models.TextField( _('Answer'), - ) + ) votes = models.IntegerField( _('Votes'), help_text=_('Total number of votes cast for this item'), default=0, - ) + ) recommendations = models.IntegerField( _('Positive Votes'), help_text=_('Number of votes for this item which were POSITIVE.'), default=0, - ) + ) last_updated = models.DateTimeField( _('Last Updated'), - help_text=_('The date on which this question was most recently ' - 'changed.'), + help_text=_('The date on which this question was most recently changed.'), blank=True, - ) + ) def save(self, *args, **kwargs): if not self.last_updated: @@ -1003,12 +1028,12 @@ class KBItem(models.Model): return '%s' % self.title class Meta: - ordering = ['title',] + ordering = ('title',) verbose_name = _('Knowledge base item') verbose_name_plural = _('Knowledge base items') def get_absolute_url(self): - return ('helpdesk_kb_item', (self.id,)) + return 'helpdesk:kb_item', (self.id,) get_absolute_url = models.permalink(get_absolute_url) @@ -1027,25 +1052,25 @@ class SavedSearch(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, verbose_name=_('User'), - ) + ) title = models.CharField( _('Query Name'), max_length=100, help_text=_('User-provided name for this query'), - ) + ) shared = models.BooleanField( _('Shared With Other Users?'), blank=True, default=False, help_text=_('Should other users see this query?'), - ) + ) query = models.TextField( _('Search Query'), help_text=_('Pickled query object. Be wary changing this.'), - ) + ) def __str__(self): if self.shared: @@ -1072,10 +1097,11 @@ class UserSettings(models.Model): settings_pickled = models.TextField( _('Settings Dictionary'), - help_text=_('This is a base64-encoded representation of a pickled Python dictionary. Do not change this field via the admin.'), + help_text=_('This is a base64-encoded representation of a pickled Python dictionary. ' + 'Do not change this field via the admin.'), blank=True, null=True, - ) + ) def _set_settings(self, data): # data should always be a Python dictionary. @@ -1121,15 +1147,7 @@ def create_usersettings(sender, instance, created, **kwargs): if created: UserSettings.objects.create(user=instance, settings=DEFAULT_USER_SETTINGS) -try: - # Connecting via settings.AUTH_USER_MODEL (string) fails in Django < 1.7. We need the actual model there. - # https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#referencing-the-user-model - if VERSION < (1, 7): - raise ValueError - models.signals.post_save.connect(create_usersettings, sender=settings.AUTH_USER_MODEL) -except: - signal_user = get_user_model() - models.signals.post_save.connect(create_usersettings, sender=signal_user) +models.signals.post_save.connect(create_usersettings, sender=settings.AUTH_USER_MODEL) @python_2_unicode_compatible @@ -1139,41 +1157,43 @@ class IgnoreEmail(models.Model): processing IMAP and POP3 mailboxes, eg mails from postmaster or from known trouble-makers. """ + class Meta: + verbose_name = _('Ignored e-mail address') + verbose_name_plural = _('Ignored e-mail addresses') + queues = models.ManyToManyField( Queue, blank=True, - help_text=_('Leave blank for this e-mail to be ignored on all ' - 'queues, or select those queues you wish to ignore this e-mail ' - 'for.'), - ) + help_text=_('Leave blank for this e-mail to be ignored on all queues, ' + 'or select those queues you wish to ignore this e-mail for.'), + ) name = models.CharField( _('Name'), max_length=100, - ) + ) date = models.DateField( _('Date'), help_text=_('Date on which this e-mail address was added'), blank=True, editable=False - ) + ) email_address = models.CharField( _('E-Mail Address'), max_length=150, help_text=_('Enter a full e-mail address, or portions with ' - 'wildcards, eg *@domain.com or postmaster@*.'), - ) + 'wildcards, eg *@domain.com or postmaster@*.'), + ) keep_in_mailbox = models.BooleanField( _('Save Emails in Mailbox?'), blank=True, default=False, - help_text=_('Do you want to save emails from this address in the ' - 'mailbox? If this is unticked, emails from this address will ' - 'be deleted.'), - ) + help_text=_('Do you want to save emails from this address in the mailbox? ' + 'If this is unticked, emails from this address will be deleted.'), + ) def __str__(self): return '%s' % self.name @@ -1198,18 +1218,14 @@ class IgnoreEmail(models.Model): own_parts = self.email_address.split("@") email_parts = email.split("@") - if self.email_address == email \ - or own_parts[0] == "*" and own_parts[1] == email_parts[1] \ - or own_parts[1] == "*" and own_parts[0] == email_parts[0] \ - or own_parts[0] == "*" and own_parts[1] == "*": + if self.email_address == email or \ + own_parts[0] == "*" and own_parts[1] == email_parts[1] or \ + own_parts[1] == "*" and own_parts[0] == email_parts[0] or \ + own_parts[0] == "*" and own_parts[1] == "*": return True else: return False - class Meta: - verbose_name = _('Ignored e-mail address') - verbose_name_plural = _('Ignored e-mail addresses') - @python_2_unicode_compatible class TicketCC(models.Model): @@ -1225,7 +1241,7 @@ class TicketCC(models.Model): ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), - ) + ) user = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -1233,28 +1249,28 @@ class TicketCC(models.Model): null=True, help_text=_('User who wishes to receive updates for this ticket.'), verbose_name=_('User'), - ) + ) email = models.EmailField( _('E-Mail Address'), blank=True, null=True, help_text=_('For non-user followers, enter their e-mail address'), - ) + ) can_view = models.BooleanField( _('Can View Ticket?'), blank=True, default=False, help_text=_('Can this CC login to view the ticket details?'), - ) + ) can_update = models.BooleanField( _('Can Update Ticket?'), blank=True, default=False, help_text=_('Can this CC login and update the ticket?'), - ) + ) def _email_address(self): if self.user and self.user.email is not None: @@ -1273,7 +1289,9 @@ class TicketCC(models.Model): def __str__(self): return '%s for %s' % (self.display, self.ticket.title) + class CustomFieldManager(models.Manager): + def get_queryset(self): return super(CustomFieldManager, self).get_queryset().order_by('ordering') @@ -1286,78 +1304,80 @@ class CustomField(models.Model): name = models.SlugField( _('Field Name'), - help_text=_('As used in the database and behind the scenes. Must be unique and consist of only lowercase letters with no punctuation.'), + help_text=_('As used in the database and behind the scenes. ' + 'Must be unique and consist of only lowercase letters with no punctuation.'), unique=True, - ) + ) label = models.CharField( _('Label'), max_length=30, help_text=_('The display label for this field'), - ) + ) help_text = models.TextField( _('Help Text'), help_text=_('Shown to the user when editing the ticket'), blank=True, null=True - ) + ) DATA_TYPE_CHOICES = ( - ('varchar', _('Character (single line)')), - ('text', _('Text (multi-line)')), - ('integer', _('Integer')), - ('decimal', _('Decimal')), - ('list', _('List')), - ('boolean', _('Boolean (checkbox yes/no)')), - ('date', _('Date')), - ('time', _('Time')), - ('datetime', _('Date & Time')), - ('email', _('E-Mail Address')), - ('url', _('URL')), - ('ipaddress', _('IP Address')), - ('slug', _('Slug')), - ) + ('varchar', _('Character (single line)')), + ('text', _('Text (multi-line)')), + ('integer', _('Integer')), + ('decimal', _('Decimal')), + ('list', _('List')), + ('boolean', _('Boolean (checkbox yes/no)')), + ('date', _('Date')), + ('time', _('Time')), + ('datetime', _('Date & Time')), + ('email', _('E-Mail Address')), + ('url', _('URL')), + ('ipaddress', _('IP Address')), + ('slug', _('Slug')), + ) data_type = models.CharField( _('Data Type'), max_length=100, help_text=_('Allows you to restrict the data entered into this field'), choices=DATA_TYPE_CHOICES, - ) + ) max_length = models.IntegerField( _('Maximum Length (characters)'), blank=True, null=True, - ) + ) decimal_places = models.IntegerField( _('Decimal Places'), help_text=_('Only used for decimal fields'), blank=True, null=True, - ) + ) empty_selection_list = models.BooleanField( _('Add empty first choice to List?'), default=False, - help_text=_('Only for List: adds an empty first entry to the choices list, which enforces that the user makes an active choice.'), - ) + help_text=_('Only for List: adds an empty first entry to the choices list, ' + 'which enforces that the user makes an active choice.'), + ) list_values = models.TextField( _('List Values'), help_text=_('For list fields only. Enter one option per line.'), blank=True, null=True, - ) + ) ordering = models.IntegerField( _('Ordering'), help_text=_('Lower numbers are displayed first; higher numbers are listed later'), blank=True, null=True, - ) + ) def _choices_as_array(self): from StringIO import StringIO @@ -1371,18 +1391,19 @@ class CustomField(models.Model): _('Required?'), help_text=_('Does the user have to enter a value for this field?'), default=False, - ) + ) staff_only = models.BooleanField( _('Staff Only?'), - help_text=_('If this is ticked, then the public submission form will NOT show this field'), + help_text=_('If this is ticked, then the public submission form ' + 'will NOT show this field'), default=False, - ) + ) objects = CustomFieldManager() def __str__(self): - return '%s' % (self.name) + return '%s' % self.name class Meta: verbose_name = _('Custom field') @@ -1394,12 +1415,12 @@ class TicketCustomFieldValue(models.Model): ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), - ) + ) field = models.ForeignKey( CustomField, verbose_name=_('Field'), - ) + ) value = models.TextField(blank=True, null=True) @@ -1407,9 +1428,7 @@ class TicketCustomFieldValue(models.Model): return '%s / %s' % (self.ticket, self.field) class Meta: - unique_together = ('ticket', 'field'), - - class Meta: + unique_together = (('ticket', 'field'),) verbose_name = _('Ticket custom field value') verbose_name_plural = _('Ticket custom field values') @@ -1421,22 +1440,22 @@ class TicketDependency(models.Model): To help enforce this, a helper function `can_be_resolved` on each Ticket instance checks that these have all been resolved. """ + class Meta: + unique_together = (('ticket', 'depends_on'),) + verbose_name = _('Ticket dependency') + verbose_name_plural = _('Ticket dependencies') + ticket = models.ForeignKey( Ticket, verbose_name=_('Ticket'), related_name='ticketdependency', - ) + ) depends_on = models.ForeignKey( Ticket, verbose_name=_('Depends On Ticket'), related_name='depends_on', - ) + ) def __str__(self): return '%s / %s' % (self.ticket, self.depends_on) - - class Meta: - unique_together = ('ticket', 'depends_on') - verbose_name = _('Ticket dependency') - verbose_name_plural = _('Ticket dependencies') diff --git a/helpdesk/settings.py b/helpdesk/settings.py index 27cbfd59..a1ca3c0b 100644 --- a/helpdesk/settings.py +++ b/helpdesk/settings.py @@ -11,22 +11,26 @@ try: except: DEFAULT_USER_SETTINGS = None -if type(DEFAULT_USER_SETTINGS) != type(dict()): +if not isinstance(DEFAULT_USER_SETTINGS, dict): DEFAULT_USER_SETTINGS = { - 'use_email_as_submitter': True, - 'email_on_ticket_assign': True, - 'email_on_ticket_change': True, - 'login_view_ticketlist': True, - 'email_on_ticket_apichange': True, - 'tickets_per_page': 25 - } + 'use_email_as_submitter': True, + 'email_on_ticket_assign': True, + 'email_on_ticket_change': True, + 'login_view_ticketlist': True, + 'tickets_per_page': 25 + } HAS_TAG_SUPPORT = False -''' generic options - visible on all pages ''' +########################################## +# generic options - visible on all pages # +########################################## + # redirect to login page instead of the default homepage when users visits "/"? -HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = getattr(settings, 'HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT', False) +HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = getattr(settings, + 'HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT', + False) # show knowledgebase links? HELPDESK_KB_ENABLED = getattr(settings, 'HELPDESK_KB_ENABLED', True) @@ -34,14 +38,20 @@ HELPDESK_KB_ENABLED = getattr(settings, 'HELPDESK_KB_ENABLED', True) # show extended navigation by default, to all users, irrespective of staff status? HELPDESK_NAVIGATION_ENABLED = getattr(settings, 'HELPDESK_NAVIGATION_ENABLED', False) -# use public CDNs to serve jquery and other javascript by default? otherwise, use built-in static copy +# use public CDNs to serve jquery and other javascript by default? +# otherwise, use built-in static copy HELPDESK_USE_CDN = getattr(settings, 'HELPDESK_USE_CDN', False) # show dropdown list of languages that ticket comments can be translated into? -HELPDESK_TRANSLATE_TICKET_COMMENTS = getattr(settings, 'HELPDESK_TRANSLATE_TICKET_COMMENTS', False) +HELPDESK_TRANSLATE_TICKET_COMMENTS = getattr(settings, + 'HELPDESK_TRANSLATE_TICKET_COMMENTS', + False) -# list of languages to offer. if set to false, all default google translate languages will be shown. -HELPDESK_TRANSLATE_TICKET_COMMENTS_LANG = getattr(settings, 'HELPDESK_TRANSLATE_TICKET_COMMENTS_LANG', ["en", "de", "fr", "it", "ru"]) +# list of languages to offer. if set to false, +# all default google translate languages will be shown. +HELPDESK_TRANSLATE_TICKET_COMMENTS_LANG = getattr(settings, + 'HELPDESK_TRANSLATE_TICKET_COMMENTS_LANG', + ["en", "de", "fr", "it", "ru"]) # show link to 'change password' on 'User Settings' page? HELPDESK_SHOW_CHANGE_PASSWORD = getattr(settings, 'HELPDESK_SHOW_CHANGE_PASSWORD', False) @@ -50,10 +60,15 @@ HELPDESK_SHOW_CHANGE_PASSWORD = getattr(settings, 'HELPDESK_SHOW_CHANGE_PASSWORD HELPDESK_FOLLOWUP_MOD = getattr(settings, 'HELPDESK_FOLLOWUP_MOD', False) # auto-subscribe user to ticket if (s)he responds to a ticket? -HELPDESK_AUTO_SUBSCRIBE_ON_TICKET_RESPONSE = getattr(settings, 'HELPDESK_AUTO_SUBSCRIBE_ON_TICKET_RESPONSE', False) +HELPDESK_AUTO_SUBSCRIBE_ON_TICKET_RESPONSE = getattr(settings, + 'HELPDESK_AUTO_SUBSCRIBE_ON_TICKET_RESPONSE', + False) -''' options for public pages ''' +############################ +# options for public pages # +############################ + # show 'view a ticket' section on public page? HELPDESK_VIEW_A_TICKET_PUBLIC = getattr(settings, 'HELPDESK_VIEW_A_TICKET_PUBLIC', True) @@ -61,17 +76,25 @@ HELPDESK_VIEW_A_TICKET_PUBLIC = getattr(settings, 'HELPDESK_VIEW_A_TICKET_PUBLIC HELPDESK_SUBMIT_A_TICKET_PUBLIC = getattr(settings, 'HELPDESK_SUBMIT_A_TICKET_PUBLIC', True) +################################### +# options for update_ticket views # +################################### -''' options for update_ticket views ''' -# allow non-staff users to interact with tickets? this will also change how 'staff_member_required' +# allow non-staff users to interact with tickets? +# this will also change how 'staff_member_required' # in staff.py will be defined. -HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = getattr(settings, 'HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE', False) +HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = getattr(settings, + 'HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE', + False) # show edit buttons in ticket follow ups. -HELPDESK_SHOW_EDIT_BUTTON_FOLLOW_UP = getattr(settings, 'HELPDESK_SHOW_EDIT_BUTTON_FOLLOW_UP', True) +HELPDESK_SHOW_EDIT_BUTTON_FOLLOW_UP = getattr(settings, + 'HELPDESK_SHOW_EDIT_BUTTON_FOLLOW_UP', + True) # show delete buttons in ticket follow ups if user is 'superuser' -HELPDESK_SHOW_DELETE_BUTTON_SUPERUSER_FOLLOW_UP = getattr(settings, 'HELPDESK_SHOW_DELETE_BUTTON_SUPERUSER_FOLLOW_UP', False) +HELPDESK_SHOW_DELETE_BUTTON_SUPERUSER_FOLLOW_UP = getattr( + settings, 'HELPDESK_SHOW_DELETE_BUTTON_SUPERUSER_FOLLOW_UP', False) # make all updates public by default? this will hide the 'is this update public' checkbox HELPDESK_UPDATE_PUBLIC_DEFAULT = getattr(settings, 'HELPDESK_UPDATE_PUBLIC_DEFAULT', False) @@ -82,18 +105,28 @@ HELPDESK_STAFF_ONLY_TICKET_OWNERS = getattr(settings, 'HELPDESK_STAFF_ONLY_TICKE # only show staff users in ticket cc drop-down HELPDESK_STAFF_ONLY_TICKET_CC = getattr(settings, 'HELPDESK_STAFF_ONLY_TICKET_CC', False) - # allow the subject to have a configurable template. -HELPDESK_EMAIL_SUBJECT_TEMPLATE = getattr(settings, 'HELPDESK_EMAIL_SUBJECT_TEMPLATE', "{{ ticket.ticket }} {{ ticket.title|safe }} %(subject)s") +HELPDESK_EMAIL_SUBJECT_TEMPLATE = getattr( + settings, 'HELPDESK_EMAIL_SUBJECT_TEMPLATE', + "{{ ticket.ticket }} {{ ticket.title|safe }} %(subject)s") + +# default fallback locale when queue locale not found +HELPDESK_EMAIL_FALLBACK_LOCALE = getattr(settings, 'HELPDESK_EMAIL_FALLBACK_LOCALE', 'en') -''' options for staff.create_ticket view ''' +######################################## +# options for staff.create_ticket view # +######################################## + # hide the 'assigned to' / 'Case owner' field from the 'create_ticket' view? -HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO = getattr(settings, 'HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO', False) +HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO = getattr( + settings, 'HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO', False) +################# +# email options # +################# -''' email options ''' # default Queue email submission settings QUEUE_EMAIL_BOX_TYPE = getattr(settings, 'QUEUE_EMAIL_BOX_TYPE', None) QUEUE_EMAIL_BOX_SSL = getattr(settings, 'QUEUE_EMAIL_BOX_SSL', None) @@ -101,6 +134,6 @@ QUEUE_EMAIL_BOX_HOST = getattr(settings, 'QUEUE_EMAIL_BOX_HOST', None) QUEUE_EMAIL_BOX_USER = getattr(settings, 'QUEUE_EMAIL_BOX_USER', None) QUEUE_EMAIL_BOX_PASSWORD = getattr(settings, 'QUEUE_EMAIL_BOX_PASSWORD', None) - # only allow users to access queues that they are members of? -HELPDESK_ENABLE_PER_QUEUE_STAFF_PERMISSION = getattr(settings, 'HELPDESK_ENABLE_PER_QUEUE_STAFF_PERMISSION', False) +HELPDESK_ENABLE_PER_QUEUE_STAFF_PERMISSION = getattr( + settings, 'HELPDESK_ENABLE_PER_QUEUE_STAFF_PERMISSION', False) diff --git a/helpdesk/templates/helpdesk/attribution.html b/helpdesk/templates/helpdesk/attribution.html index a19571bf..82c1ea2a 100644 --- a/helpdesk/templates/helpdesk/attribution.html +++ b/helpdesk/templates/helpdesk/attribution.html @@ -1,2 +1,2 @@ {% load i18n %} -{% trans "django-helpdesk." %} +{% trans "django-helpdesk." %} diff --git a/helpdesk/templates/helpdesk/base.html b/helpdesk/templates/helpdesk/base.html index a93fe0a0..ee37ca18 100644 --- a/helpdesk/templates/helpdesk/base.html +++ b/helpdesk/templates/helpdesk/base.html @@ -74,9 +74,9 @@ - - - + + + @@ -126,7 +126,6 @@

{% include "helpdesk/debug.html" %} diff --git a/helpdesk/templates/helpdesk/email_ignore_list.html b/helpdesk/templates/helpdesk/email_ignore_list.html index 4ad6f480..3dda68b7 100644 --- a/helpdesk/templates/helpdesk/email_ignore_list.html +++ b/helpdesk/templates/helpdesk/email_ignore_list.html @@ -37,7 +37,7 @@ {{ ignore.date }} {% for queue in ignore.queues.all %}{{ queue.slug }}{% if not forloop.last %}, {% endif %}{% empty %}{% trans "All" %}{% endfor %} {% if ignore.keep_in_mailbox %}{% trans "Keep" %}{% endif %} - + {% endfor %} @@ -53,7 +53,6 @@ -

{% trans "Note: If the 'Keep' option is not selected, emails sent from that address will be deleted permanently." %}

{% endblock %} diff --git a/helpdesk/templates/helpdesk/help_api.html b/helpdesk/templates/helpdesk/help_api.html deleted file mode 100644 index a73ca5a9..00000000 --- a/helpdesk/templates/helpdesk/help_api.html +++ /dev/null @@ -1,277 +0,0 @@ -{% extends "helpdesk/help_base.html" %} - -{% block title %}django-helpdesk API Documentation{% endblock %} -{% block heading %}django-helpdesk API Documentation{% endblock %} - -{% block content %} -

Contents

- - -

Deprecation Warning

- -

This API has been deprecated and will be removed in January 2016. Please See the GitHub Issue Tracker for more details.

-

Do not build new integrations using this API.

- -

We recommend using django-rest-framework or similar for all integrations.

- -

Introduction

- -

django-helpdesk provides a powerful API to allow you to interact with your helpdesk tickets by a means not otherwise provided by the helpdesk.

- -

For example, you may use this API to implement a system to automatically open a ticket when an invoice is raised in your invoicing system, or to automatically close a ticket from an instant messenger application.

- -

Your use of this system is open-ended: most business cases should be addressible with a little bit of coding to allow you to interact nicely with your helpdesk.

- -

Request Basics & Authentication

- -

All requests to the API must be made using HTTP POST requests. Any request that is not made using POST will raise an error.

- -

Your requests must be made up of the following elements:

- -
    -
  1. A method, or action. This tells the API what core functionality to execute.
  2. -
  3. A username and password which are valid and active within your helpdesk system. You may wish to create a specific API user just for API usage.
  4. -
  5. A set of data to be saved into the database. This data will vary from request to request, and is outlined in Methods below.
  6. -
- -

To build your request, send a HTTP POST request to {% url 'helpdesk_api' "method" %}, where method is the name of a valid method from the list below.

- -

Your POST must include both user and password parameters.

- -

A sample request for the method hold_ticket may look like this:

- -
    -
  • A HTTP POST to {% url 'helpdesk_api' "hold_ticket" %}
  • -
  • A set of POST data containing:
      -
    • username=susan
    • -
    • password=fido
    • -
    • ticket=31794
    • -
  • -
- -

To complete this from a command-line using the cURL application, you may use a command such as this:

- -
/usr/bin/curl {% url 'helpdesk_api' "hold_ticket" %} --data "user=susan&password=fido&ticket=31794"
- -

In PHP, providing you have access to the cURL libraries, you may use code such as this:

- -
<?php
-$api = curl_init();
-curl_setopt($api, CURLOPT_URL, "{% url 'helpdesk_api' "hold_ticket" %}");
-curl_setopt($api, CURLOPT_POST, 1);
-curl_setopt($api, CURLOPT_POSTFIELDS, "user=susan&password=fido&ticket=31794");
-$result = curl_exec($api);
-curl_close($api);
-echo $result;
-?>
- -

Note that cURL expects all data to be urlencoded, this is left as an exercise for the reader.

- -

Responses

- -

The API system makes proper use of the following HTTP response codes:

- -
-
200
-
OK - Data updated successfully
- -
400
-
ERROR - Generic error. See returned text for details
- -
404
-
ERROR - Data not found (eg, incorrect ticket). See returned text for details
- -
403
-
ERROR - Invalid permissions (eg, incorrect username and/or password)
- -
405
-
ERROR - Invalid method. You probably tried using GET, PUT or DELETE however we require POST.
-
- -

Responses will have one of two content-types:

- -
-
text/plain
-
Any error messages, or simple responses (eg a ticket ID)
- -
text/json
-
Any complex responses, such as a list of data.
-
- -

Method Documentation

- -

The following public methods are available for use via the API. Each of them requires a valid request and authentication, and each has it's own parameters as described below.

- - - -

create_ticket

- -

This method creates a new helpdesk ticket.

- -

Parameters

- -
-
queue
-
Queue ID (use list_queues to get queue ID's) - this is an integer field.
- -
title
-
Title or header of this ticket. Character field, maximum 100 characters.
- -
submitter_email
-
(Optional) e-mail address of the person submitting this ticket. This e-mail address will receive copies of all public updates to this ticket, and will receive a notification when the ticket is created.
- -
assigned_to
-
(Optional) Integer ID of the user to which this ticket should be assigned. Use find_user to find a user ID from a username.
- -
priority
-
(Optional) Priority as an integer from 1 (high) to 5 (low). Defaults to 3 if no priority given.
-
- -

Response

- -

This method responds with plain-text.

- -

If you receive a 200 OK response, then the content of the response will be the ticket ID.

- -

delete_ticket

- -

When given a ticket ID and confirmation, this method will delete a ticket entirely. This also deletes any followups, attachments, and other details.

- -

Parameters

- -
-
ticket
-
The numeric ticket ID to be deleted
- -
confirm
-
You must provide this field, with any value, to enable deletion to continue
-
- -

Response

- -

A standard 200 OK response is given on success, or an error message on failure.

- -

hold_ticket

- -

If a ticket needs to be placed on hold, preventing it from being escalated, use this method.

- -

Parameters

-
-
ticket
-
The numeric ticket ID to be placed on hold
-
- -

Response

- -

A standard 200 OK response is given on success, or an error message on failure.

- - -

unhold_ticket

- -

If a ticket is currently on hold and you wish to remove that hold, use this method.

- -

Parameters

-
-
ticket
-
The numeric ticket ID to be taken off hold
-
- -

Response

- -

A standard 200 OK response is given on success, or an error message on failure.

- - -

add_followup

- -

This method adds a comment / followup to a ticket. The followup can be public, in which case it is e-mailed to the submitter, or private. The followup will also be sent to others involved in the ticket: The owner and the queue notification / CC address.

- -

Parameters

- -
-
ticket
-
The numeric ticket ID to which this followup should be added
- -
message
-
Text of 'unlimited' length - optionally formatted with HTML - to add to the message.
- -
public
-
Either 'y' for public, or 'n' for private. This is optional, and it is assumed that followups are private if it is not provided. Private tickets are not e-mailed to the ticket submitter.
-
- -

Response

- -

A standard 200 OK response is given on success, or an error message on failure.

- - -

resolve

- -

This method adds a resolution to a ticket and marks it as resolved. The resolution will be e-mailed to everybody involved with the ticket, including the submitter.

- -

Parameters

- -
-
ticket
-
The numeric ticket ID to which this followup should be added
- -
resolution
-
Text of 'unlimited' length - optionally formatted with HTML. This is the resolution for this ticket.
-
- -

Response

- -

A standard 200 OK response is given on success, or an error message on failure.

- - -

list_queues

- -

This method provides a JSON-parsable list of queues, letting you access the individual queue ID in order to create tickets.

- -

Response

- -

This method responds with json.

- -

It provides a list of queues in JSON format. The fields provided are ID and Title.

- - -

find_user

- -

When given a username, this method provides the related numeric user ID - commonly used when creating or reassigning tickets.

- -

Parameters

- -
-
username
-
The case-sensitive username of the user for which you require the user ID
-
- -

Response

- -

This method responds with plain-text.

- -

If you receive a 200 OK response, then the content of the response will be the users ID.

-{% endblock %} diff --git a/helpdesk/templates/helpdesk/include/stats.html b/helpdesk/templates/helpdesk/include/stats.html index 2cddcdc5..d938e0d5 100644 --- a/helpdesk/templates/helpdesk/include/stats.html +++ b/helpdesk/templates/helpdesk/include/stats.html @@ -22,7 +22,7 @@ - {% if entry.1 > 0 %}{% else %}{% endif %} + {% if entry.1 > 0 %}{% else %}{% endif %} @@ -17,27 +17,28 @@ {% if helpdesk_settings.HELPDESK_NAVIGATION_ENABLED and user.is_authenticated or user.is_staff %}