Compare commits

...

140 Commits

Author SHA1 Message Date
Ariel Rin
08e9676760 Version Bump v2.8.1 2020-12-07 04:46:55 +00:00
Ariel Rin
15ae737522 Merge branch 'user-agent' into 'master'
Bump minimum django-esi and add User Agent header.

See merge request allianceauth/allianceauth!1275
2020-12-07 04:32:10 +00:00
Ariel Rin
50ec9e563e Merge branch 'celery_result_logger' into 'master'
Remove result from default log message on task success

See merge request allianceauth/allianceauth!1273
2020-12-07 04:30:52 +00:00
colcrunch
cb40649f8b Add note to local.py on ESI_CONTACT_EMAIL setting 2020-12-06 22:54:31 -05:00
colcrunch
bccead0881 Add mention of ESI_USER_CONTACT_EMAIL to install documentation. 2020-12-02 17:42:03 -05:00
colcrunch
35ae710624 Add ESI_USER_CONTACT_EMAIL setting to local.py 2020-12-01 23:25:48 -05:00
colcrunch
75de4518f2 Use app_info_text in EveSwaggerProvider to set the User-Agent header on ESI requests. 2020-12-01 22:40:09 -05:00
colcrunch
bfcdfea6c8 Update minimum django-esi version to ensure support for user-agent header. 2020-12-01 17:17:55 -05:00
Ariel Rin
471553fa88 Add a minimal set of django deps needed to build docs 2020-12-01 07:14:22 +00:00
Ariel Rin
db59f5f69b Add Django to docs requirements 2020-11-30 14:41:01 +00:00
Ariel Rin
1b5413646e Correct Typos in Docs Requirements 2020-11-30 14:37:42 +00:00
Ariel Rin
0337d2517c use limited set of python packages for docs 2020-11-30 14:30:23 +00:00
ErikKalkoken
87e6eb9688 Remove result from default log message on task success 2020-11-28 22:10:41 +01:00
Ariel Rin
7b8c246ef8 Merge branch 'master' into 'master'
[Quickfix] Missing ^ added

See merge request allianceauth/allianceauth!1271
2020-11-19 13:26:53 +00:00
Peter Pfeufer
a268a8980a Missing ^ added 2020-11-18 22:50:27 +01:00
Ariel Rin
3b516c338e Merge branch 'groupmanagement-revamp' into 'master'
Group management improvements

See merge request allianceauth/allianceauth!1270
2020-11-17 11:56:16 +00:00
Peter Pfeufer
9952685805 textfield should not be Null=True 2020-11-16 18:04:57 +01:00
Peter Pfeufer
2f59c8df22 And of course I missed something ... 2020-10-26 01:10:41 +01:00
Peter Pfeufer
6cd0a42791 reverted code formatting for Aaron :-) 2020-10-26 01:06:58 +01:00
Peter Pfeufer
4c42153bfd stop member count header from line breaking 2020-10-25 13:53:17 +01:00
Peter Pfeufer
603bd9c37c make description a real description
textfield instead of charfield. a bit more user friendly in the backend
2020-10-25 12:40:10 +01:00
Peter Pfeufer
87c0c3ac73 tables formatted properly
align center is horrible to read ....
2020-10-25 11:55:03 +01:00
Peter Pfeufer
8a91e7f6ac navactive status fixed in left menu and top menu 2020-10-25 11:22:10 +01:00
Peter Pfeufer
281dbdbb01 proper URL structure established 2020-10-25 11:21:35 +01:00
Ariel Rin
8980d8d32f Version bump to 2.8.0 Stable 2020-10-13 05:33:54 +00:00
Ariel Rin
9d6cf9a62e Merge branch 'transifex' into 'master'
Add French and Japanese Translations + QoL Translation Fixes

See merge request allianceauth/allianceauth!1263
2020-10-13 04:17:37 +00:00
Ariel Rin
0fabb2b368 Add French and Japanese Translations + QoL Translation Fixes 2020-10-13 04:17:37 +00:00
Ariel Rin
9801ca0314 Merge branch 'emailoverrideredirect' into 'master'
Fix Redirect to dashboard if not verifying email

See merge request allianceauth/allianceauth!1268
2020-10-13 04:08:15 +00:00
Ariel Rin
fd86b26b39 Redirect to dashboard if not verifying email 2020-10-13 13:25:00 +10:00
Ariel Rin
b0dbef1587 Merge branch 'master' into 'master'
Expand mumble pwhash field to allow for passlib 1.7.3+

See merge request allianceauth/allianceauth!1267
2020-10-11 10:34:44 +00:00
Ariel Rin
a6e60bc23b expand mumble certhash to allow for hmac-sha-256 2020-10-11 20:11:56 +10:00
Ariel Rin
137e8a876d Merge branch 'add-corp-and-alliance-tags-to-srp' into 'master'
Add alliance and corp ticker to pilot name

See merge request allianceauth/allianceauth!1265
2020-10-11 03:42:56 +00:00
Ariel Rin
fe9538253f Merge branch 'highlight-active-menu-item' into 'master'
Highlight active menu item

See merge request allianceauth/allianceauth!1266
2020-10-11 03:41:17 +00:00
Peter Pfeufer
edda2c248e highlight active menu item 2020-10-02 20:12:21 +02:00
Peter Pfeufer
62275639e3 Added alliance and corp ticker to pilot name
Takes care of https://gitlab.com/allianceauth/allianceauth/-/issues/1228
2020-10-01 20:14:54 +02:00
Ariel Rin
d0c68b82f4 Merge branch 'docs' into 'master'
Docs Sphinx Upgrades

See merge request allianceauth/allianceauth!1264
2020-10-01 09:17:36 +00:00
Ariel Rin
78b5953bdf Merge branch 'master' of https://gitlab.com/allianceauth/allianceauth into docs 2020-10-01 18:59:14 +10:00
Ariel Rin
25e565b099 Docs Requirement upgrades 2020-10-01 18:54:04 +10:00
Ariel Rin
1fe0f78ad7 Exclude django-redis-cache 2.1.3 2020-10-01 01:59:48 +00:00
Ariel Rin
fc8b68156f Merge branch 'patch-4' into 'master'
Fixing FA icon

See merge request allianceauth/allianceauth!1262
2020-09-29 05:10:30 +00:00
Peter Pfeufer
b47cd197ce Fixing FA icon 2020-09-28 21:07:08 +00:00
Ariel Rin
3943426c4c Version Bump 2.8.0a2 2020-09-21 06:25:16 +00:00
Ariel Rin
08a9bd42a3 Merge branch 'django3' into 'master'
Django 3.1.1 bring up

See merge request allianceauth/allianceauth!1256
2020-09-21 06:16:44 +00:00
Ariel Rin
b2ff339efe Merge branch 'gitlabci2' into 'master'
Update Gitlab Deploy Python Version, Debian Distro to Stable

See merge request allianceauth/allianceauth!1260
2020-09-21 06:15:40 +00:00
Ariel Rin
c604131e04 Update Deploy Runner 2020-09-21 12:12:02 +10:00
Ariel Rin
f17607f126 Merge branch 'transifex' into 'master'
Update From Transifex

See merge request allianceauth/allianceauth!1258
2020-09-21 01:45:16 +00:00
Ariel Rin
94e455a57b Update From Transifex 2020-09-21 01:45:16 +00:00
Ariel Rin
3c9149db4a Merge branch 'improve_authtuilts_add_permission' into 'master'
Improve auth utils for permissions

See merge request allianceauth/allianceauth!1255
2020-09-21 01:09:03 +00:00
Ariel Rin
96cc615c07 Merge branch 'docs_mumbleavatars' into 'master'
Docs: Mumble Avatars Feature

See merge request allianceauth/allianceauth!1250
2020-09-21 00:01:35 +00:00
Ariel Rin
cd1f4a1c2b Docs: Mumble Avatars Feature 2020-09-21 00:01:35 +00:00
Ariel Rin
e0f99a42db Merge branch 'exiom-srp-update' into 'master'
SRP Module - Added Datatables & Sorting, Standardized Date/Time for Overall AA Consistency

See merge request allianceauth/allianceauth!1254
2020-09-20 23:55:22 +00:00
Exiom
3506e417d4 SRP Module - Added Datatables & Sorting, Standardized Date/Time for Overall AA Consistency 2020-09-20 23:55:22 +00:00
AaronKable
36197e2212 swap to reverse_lazy 2020-09-18 23:32:36 +08:00
AaronKable
fc5f42d01e remove whitespace in setup.py 2020-09-18 22:16:49 +08:00
AaronKable
e26d3767e0 update models as NullBooleanField is deprecated. 2020-09-18 22:16:24 +08:00
AaronKable
046b37c76a update auth and group model admins for django 3.1 2020-09-18 22:04:59 +08:00
AaronKable
925ff3e116 remove django req's from tox, they are managed in setup.py 2020-09-18 22:04:05 +08:00
AaronKable
e5ede4f7b6 Cant Reference what is already deleted 2020-09-18 22:03:16 +08:00
AaronKable
ded9301527 initial django3 bringup 2020-09-18 11:45:37 +08:00
ErikKalkoken
bd1ed6ff73 Add user as return value to add permission methods 2020-09-15 12:35:58 +02:00
Ariel Rin
feb65980d4 Merge branch 'fix_group_count_badge' into 'master'
Fix group count badge showing at zero

Closes #1258

See merge request allianceauth/allianceauth!1253
2020-09-12 02:05:22 +00:00
Ariel Rin
e81d75a782 Merge branch 'docs_settings_fix' into 'master'
Remove erroneous indents from settings in service module docs

See merge request allianceauth/allianceauth!1252
2020-09-12 02:04:37 +00:00
ErikKalkoken
ff305d13ae Fix group count badge showing at zero 2020-09-11 23:54:56 +02:00
colcrunch
8bcbc1a779 Remove erroneous indents from settings in service module docs. (Checked other docs, and there do not appear to be any more errors of this type) 2020-09-11 12:51:17 -04:00
Ariel Rin
3874aa6fee Version Bump 2.8.0a1 2020-09-11 11:52:20 +00:00
Ariel Rin
103e9f3a11 Merge branch 'discourse_beta' into 'master'
Discourse API with external package

See merge request allianceauth/allianceauth!1251
2020-09-11 11:33:19 +00:00
Ariel Rin
d02c25f421 Merge branch 'feature_menu_item_badges' into 'master'
Add menu item badge feature and update group icons

See merge request allianceauth/allianceauth!1240
2020-09-11 11:33:14 +00:00
Erik Kalkoken
228af38a4a Add menu item badge feature and update group icons 2020-09-11 11:33:14 +00:00
AaronKable
051a48885c discourse API with external package 2020-09-11 17:19:54 +08:00
Ariel Rin
6bcdc6052f Merge branch 'local-delivery' into 'master'
JS/CSS/Font Refactoring for use with AA-GDPR Package

Closes #1217

See merge request allianceauth/allianceauth!1247
2020-09-11 04:13:01 +00:00
Ariel Rin
af3527e64f Revert "load bootswatch less locally #1217"
This reverts commit 3a9a7267ea8734ba0a5cf1d0fea632eb2276d45c.
2020-09-11 04:13:01 +00:00
Ariel Rin
17ef3dd07a Merge branch 'srp_fix' into 'master'
Use request.scheme to get the http/https for the site

See merge request allianceauth/allianceauth!1249
2020-09-11 03:05:06 +00:00
AaronKable
1f165ecd2a use request.scheme to get the http/https for the site 2020-09-07 19:10:58 +08:00
Ariel Rin
70d1d450a9 Add Korean and Russian as features 2020-09-03 12:24:23 +00:00
Ariel Rin
b667892698 Version Bump 2.7.5 2020-09-01 02:09:05 +00:00
Ariel Rin
dc11add0e9 Merge branch 'discordapp.com-deprecation' into 'master'
discord.com replaces discordapp.com

See merge request allianceauth/allianceauth!1248
2020-09-01 01:53:25 +00:00
Ariel Rin
cb429a0b88 discord.com replaces discordapp.com 2020-09-01 11:20:57 +10:00
Ariel Rin
b51039cfc0 Merge branch 'docs' into 'master'
Add Optimizing Mumble to Services docs

See merge request allianceauth/allianceauth!1243
2020-09-01 01:11:49 +00:00
Ariel Rin
eadd959d95 Merge branch 'fix_celery_once_backend' into 'master'
Fix celery once not working properly

See merge request allianceauth/allianceauth!1246
2020-08-25 06:13:59 +00:00
Erik Kalkoken
1856e03d88 Fix celery once not working properly 2020-08-25 06:13:59 +00:00
Ariel Rin
7dcfa622a3 Merge branch 'issue_1234_exiom' into 'master'
Month Ordering Fix for Group Management Audit Logs

See merge request allianceauth/allianceauth!1245
2020-08-25 06:07:45 +00:00
Exiom
64251b9b3c Fix Date/Time Month Ordering #1234 2020-08-21 03:57:24 +00:00
Exiom
6b073dd5fc Fix Date/Time Month Ordering #1234 2020-08-21 03:33:35 +00:00
Ariel Rin
0911fabfb2 Merge branch 'issue_1234' into 'master'
Correct Month Ordering in Group Management Audit Logs

Closes #1234

See merge request allianceauth/allianceauth!1244
2020-08-20 07:11:47 +00:00
Ariel Rin
050d3f5e63 use month numerical 2020-08-20 16:55:18 +10:00
Ariel Rin
bbe3f78ad1 Grammar and Spelling Corrections 2020-08-20 15:19:50 +10:00
Ariel Rin
8204c18895 Add Optimzing Mumble 2020-08-20 15:09:07 +10:00
Ariel Rin
b91c788897 Merge branch 'bulk-affiliations' into 'master'
Reduce run time for eve online model updates

See merge request allianceauth/allianceauth!1227
2020-08-20 03:14:40 +00:00
Erik Kalkoken
1d20a3029f Only update characters if they have changed corp or alliance by bulk calling affiliations before calling character tasks. 2020-08-20 03:14:40 +00:00
Ariel Rin
9cfebc9ae3 Version Bump to 2.7.4 2020-08-17 06:34:55 +00:00
Ariel Rin
ddabb4539b Merge branch 'fix_admin_status_tags_bug' into 'master'
Bugfix: Loading of dashboard fails with 'NoneType object is not iterable' from status_tags

See merge request allianceauth/allianceauth!1237
2020-08-14 02:26:12 +00:00
Ariel Rin
ada35e221b Merge branch 'transifex' into 'master'
Update from Transifex

See merge request allianceauth/allianceauth!1241
2020-08-14 02:24:07 +00:00
Ariel Rin
6fef9d904e Update from Transifex 2020-08-14 02:24:07 +00:00
Ariel Rin
67cf2b5904 Merge branch 'fontawesomev5' into 'master'
Remove FA v4 shims, bump FA to 5.14

Closes #1248

See merge request allianceauth/allianceauth!1242
2020-08-14 02:21:41 +00:00
Ariel Rin
3bebe792f6 Remove FA v4 shims, bump to fa 5.14 2020-08-14 12:01:08 +10:00
ErikKalkoken
00b4d89181 Fix status tags bug and remove unused context from status_overview tag 2020-07-27 14:53:25 +02:00
Ariel Rin
f729c6b650 Merge branch 'patch-3' into 'master'
Update Mumble documentation on setting a server password

Closes #1252

See merge request allianceauth/allianceauth!1236
2020-07-24 11:18:02 +00:00
colcrunch
df95f8c3f3 Merge branch 'discord_improvements' into 'master'
Fix error 500 on service page for Discord and add feature "group_to_role"

See merge request allianceauth/allianceauth!1235
2020-07-23 20:58:26 +00:00
Erik Kalkoken
fe36e57d72 Fix error 500 on service page for Discord and add feature "group_to_role" 2020-07-23 20:58:26 +00:00
Peter Pfeufer
31197812b6 Update Mumble documentation on setting a server password (#1252) 2020-07-22 12:18:52 +00:00
Ariel Rin
bd3fe01a12 correct task import for manual model population 2020-07-14 12:25:05 +00:00
col_crunch
39f7f32b7d Version bump. 2020-07-13 15:32:54 -04:00
colcrunch
b4522a1277 Merge branch 'enable_django_esi_20' into 'master'
Enable django-esi 2.0 dependency

See merge request allianceauth/allianceauth!1232
2020-07-13 18:54:21 +00:00
colcrunch
bb6a7e8327 Merge branch 'issue_1250' into 'master'
Fix Discord service issues and improve dashboard

Closes #1250

See merge request allianceauth/allianceauth!1229
2020-07-13 18:54:08 +00:00
colcrunch
9bd42a7579 Merge branch 'docu_update_contributions' into 'master'
Add contributing chapter to docs

See merge request allianceauth/allianceauth!1233
2020-07-13 18:52:30 +00:00
Erik Kalkoken
b41430e5a3 Add contributing chapter to docs 2020-07-13 18:52:29 +00:00
ErikKalkoken
595353e838 Enable using django-esi 2.0 2020-07-11 12:35:16 +02:00
ErikKalkoken
f1a21bb856 Add state info to dashboard, improve stat change notifications, improve auth tests 2020-07-03 14:58:45 +02:00
ErikKalkoken
e44c2935f9 Version bump for alpha testing 2020-07-03 13:29:00 +02:00
ErikKalkoken
4d546f948d Fix state role not always updated due to lazy properties 2020-07-02 21:26:40 +02:00
ErikKalkoken
3bab349d7b Fix tests 2020-06-30 00:15:48 +02:00
ErikKalkoken
eef6126ef8 Improve state backend fix, add tests for state backend and service signal changes 2020-06-30 00:01:40 +02:00
ErikKalkoken
5c7478fa39 Fix update_nickname runs on ever save of userprofile, fix nickname not updated after main's name changes 2020-06-28 21:38:25 +02:00
ErikKalkoken
64b72d0b06 Fix service signals for state change 2020-06-28 17:14:16 +02:00
ErikKalkoken
b266a98b25 Add more tests for state change 2020-06-28 14:56:01 +02:00
ErikKalkoken
8a27de5df8 Fix state change does not update groups 2020-06-28 01:45:51 +02:00
ErikKalkoken
f9b5310fce Fix user account not deleted when demoted to guest 2020-06-27 23:32:12 +02:00
ErikKalkoken
fdce173969 Add tests to fix new bugs 2020-06-27 16:18:06 +02:00
ErikKalkoken
7b9ddf90c1 Fix tests for tox 2020-06-25 23:38:20 +02:00
ErikKalkoken
580c8c19de Update request timeout default 2020-06-25 22:32:29 +02:00
ErikKalkoken
55cc77140e Fix bug blocking superuser from adding Discord bot 2020-06-25 22:19:48 +02:00
Ariel Rin
93c89dd7cc Merge branch 'wother-master-patch-74872' into 'master'
Updated discord.md

See merge request allianceauth/allianceauth!1228
2020-06-22 03:19:27 +00:00
Carter Foulger
c970cbbd2d Updated discord.md with additional troubleshooting
steps.
2020-06-19 19:45:22 +00:00
Ariel Rin
9ea55fa51f Version Bump 2.7.2 2020-06-11 03:49:06 +00:00
Ariel Rin
5775a11b4e Merge branch 'replace_context_manager_groups' into 'master'
Improve page load performance by replacing groups context manager

See merge request allianceauth/allianceauth!1219
2020-06-11 03:41:31 +00:00
Ariel Rin
1a666b6584 Merge branch 'fontawesomev5' into 'master'
Font Awesome V5 Update

Closes #1207

See merge request allianceauth/allianceauth!1224
2020-06-11 03:33:37 +00:00
Ariel Rin
35407a2108 Font Awesome V5 Update 2020-06-11 03:33:37 +00:00
Ariel Rin
71fb19aa22 Merge branch 'version_battle' into 'master'
Make version relevant to an admin

See merge request allianceauth/allianceauth!1220
2020-06-11 03:13:13 +00:00
AaronKable
b7d7f7b8ce latest stable 2020-06-11 10:47:05 +08:00
Ariel Rin
59b983edcc Merge branch 'future' into 'master'
Remove Future dependency

Closes #1242

See merge request allianceauth/allianceauth!1223
2020-06-11 01:01:23 +00:00
Ariel Rin
1734d034e1 Merge branch 'evemodel_integers' into 'master'
Change EveModels to Integer ID fields

See merge request allianceauth/allianceauth!1211
2020-06-09 13:10:10 +00:00
Aaron Kable
7f7500ff0c Change EveModels to Integer ID fields 2020-06-09 13:10:10 +00:00
Ariel Rin
ce77c24e5c Exclude Celery 4.4.4 2020-06-09 11:30:13 +10:00
Ariel Rin
5469a591c0 Remove Future dependency 2020-06-09 11:10:32 +10:00
Ariel Rin
a4befc5e59 Version Bump 2.7.1 2020-06-09 00:25:30 +00:00
Ariel Rin
1ee8065592 Merge branch 'issue_1244' into 'master'
Fix sleep length must be non-negative

Closes #1244

See merge request allianceauth/allianceauth!1222
2020-06-09 00:23:36 +00:00
ErikKalkoken
e4e3bd44fc Fix sleep length must be non-negative 2020-06-08 14:59:22 +02:00
AaronKable
c75de07c2e Only show Pre-Release when available 2020-06-08 20:47:05 +08:00
AaronKable
e928131809 make version relevant to an admin 2020-06-08 19:18:11 +08:00
ErikKalkoken
bbb70c93d9 Initial 2020-06-06 17:59:23 +02:00
184 changed files with 8635 additions and 2265 deletions

View File

@@ -41,7 +41,7 @@ test-3.8-all:
deploy_production: deploy_production:
stage: deploy stage: deploy
image: python:3.6-stretch image: python:3.8-buster
before_script: before_script:
- pip install twine - pip install twine

View File

@@ -18,10 +18,6 @@ formats: all
# Optionally set the version of Python and requirements required to build your docs # Optionally set the version of Python and requirements required to build your docs
python: python:
version: 3.7 version: 3.7
install: install:
- method: pip - requirements: docs/requirements.txt
path: .
extra_requirements:
- testing
system_packages: true

View File

@@ -36,7 +36,7 @@ Main features:
- Can be easily extended with additional services and apps. Many are provided by the community and can be found here: [Community Creations](https://gitlab.com/allianceauth/community-creations) - Can be easily extended with additional services and apps. Many are provided by the community and can be found here: [Community Creations](https://gitlab.com/allianceauth/community-creations)
- Chinese :cn:, English :us:, German :de: and Spanish :es: localization - English :flag_gb:, Chinese :flag_cn:, German :flag_de:, Spanish :flag_es:, Korean :flag_kr: and Russian :flag_ru: localization
For further details about AA - including an installation guide and a full list of included services and plugin apps - please see the [official documentation](http://allianceauth.rtfd.io). For further details about AA - including an installation guide and a full list of included services and plugin apps - please see the [official documentation](http://allianceauth.rtfd.io).

View File

@@ -1,7 +1,7 @@
# This will make sure the app is always imported when # This will make sure the app is always imported when
# Django starts so that shared_task will use this app. # Django starts so that shared_task will use this app.
__version__ = '2.7.0' __version__ = '2.8.1'
__title__ = 'Alliance Auth' __title__ = 'Alliance Auth'
__url__ = 'https://gitlab.com/allianceauth/allianceauth' __url__ = 'https://gitlab.com/allianceauth/allianceauth'
NAME = '%s v%s' % (__title__, __version__) NAME = '%s v%s' % (__title__, __version__)

View File

@@ -100,7 +100,7 @@ class UserProfileInline(admin.StackedInline):
formset.get_form_kwargs = get_kwargs formset.get_form_kwargs = get_kwargs
return formset return formset
def has_add_permission(self, request): def has_add_permission(self, request, obj=None):
return False return False
def has_delete_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None):
@@ -549,7 +549,7 @@ class PermissionAdmin(admin.ModelAdmin):
def admin_name(obj): def admin_name(obj):
return str(obj) return str(obj)
def has_add_permission(self, request): def has_add_permission(self, request, obj=None):
return False return False
def has_delete_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None):

View File

@@ -1,7 +1,8 @@
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import Permission
from django.contrib.auth.models import User
import logging import logging
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User, Permission
from .models import UserProfile, CharacterOwnership, OwnershipRecord from .models import UserProfile, CharacterOwnership, OwnershipRecord
@@ -11,9 +12,11 @@ logger = logging.getLogger(__name__)
class StateBackend(ModelBackend): class StateBackend(ModelBackend):
@staticmethod @staticmethod
def _get_state_permissions(user_obj): def _get_state_permissions(user_obj):
profile_state_field = UserProfile._meta.get_field('state') """returns permissions for state of given user object"""
user_state_query = 'state__%s__user' % profile_state_field.related_query_name() if hasattr(user_obj, "profile") and user_obj.profile:
return Permission.objects.filter(**{user_state_query: user_obj}) return Permission.objects.filter(state=user_obj.profile.state)
else:
return Permission.objects.none()
def get_state_permissions(self, user_obj, obj=None): def get_state_permissions(self, user_obj, obj=None):
return self._get_permissions(user_obj, obj, 'state') return self._get_permissions(user_obj, obj, 'state')

View File

@@ -1,6 +1,8 @@
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from allianceauth.authentication.models import User
class RegistrationForm(forms.Form): class RegistrationForm(forms.Form):
email = forms.EmailField(label=_('Email'), max_length=254, required=True) email = forms.EmailField(label=_('Email'), max_length=254, required=True)
class _meta:
model = User

View File

@@ -10,5 +10,5 @@ urlpatterns = [
url(r'^register/$', views.RegistrationView.as_view(), name='registration_register'), url(r'^register/$', views.RegistrationView.as_view(), name='registration_register'),
url(r'^register/complete/$', views.registration_complete, name='registration_complete'), url(r'^register/complete/$', views.registration_complete, name='registration_complete'),
url(r'^register/closed/$', views.registration_closed, name='registration_disallowed'), url(r'^register/closed/$', views.registration_closed, name='registration_disallowed'),
url(r'', include('registration.auth_urls')), url(r'', include('django.contrib.auth.urls')),
] ]

View File

@@ -73,11 +73,17 @@ class UserProfile(models.Model):
if commit: if commit:
logger.info('Updating {} state to {}'.format(self.user, self.state)) logger.info('Updating {} state to {}'.format(self.user, self.state))
self.save(update_fields=['state']) self.save(update_fields=['state'])
notify(self.user, _('State Changed'), notify(
_('Your user state has been changed to %(state)s') % ({'state': state}), self.user,
'info') _('State changed to: %s' % state),
_('Your user\'s state is now: %(state)s')
% ({'state': state}),
'info'
)
from allianceauth.authentication.signals import state_changed from allianceauth.authentication.signals import state_changed
state_changed.send(sender=self.__class__, user=self.user, state=self.state) state_changed.send(
sender=self.__class__, user=self.user, state=self.state
)
def __str__(self): def __str__(self):
return str(self.user) return str(self.user)

View File

@@ -23,9 +23,7 @@ def trigger_state_check(state):
check_states = State.objects.filter(priority__lt=state.priority) check_states = State.objects.filter(priority__lt=state.priority)
for profile in UserProfile.objects.filter(state__in=check_states): for profile in UserProfile.objects.filter(state__in=check_states):
if state.available_to_user(profile.user): if state.available_to_user(profile.user):
profile.state = state profile.assign_state(state)
profile.save(update_fields=['state'])
state_changed.send(sender=state.__class__, user=profile.user, state=state)
@receiver(m2m_changed, sender=State.member_characters.through) @receiver(m2m_changed, sender=State.member_characters.through)

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Dashboard" %}{% endblock %} {% block page_title %}{% trans "Dashboard" %}{% endblock %}
@@ -14,7 +14,11 @@
<div class="col-sm-6 text-center"> <div class="col-sm-6 text-center">
<div class="panel panel-primary" style="height:100%"> <div class="panel panel-primary" style="height:100%">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% trans "Main Character" %}</h3> <h3 class="panel-title">
{% blocktrans with state=request.user.profile.state %}
Main Character (State: {{ state }})
{% endblocktrans %}
</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
{% if request.user.profile.main_character %} {% if request.user.profile.main_character %}

View File

@@ -1,7 +1,7 @@
{% load staticfiles %} {% extends 'public/base.html' %}
{% load static %}
{% load bootstrap %} {% load bootstrap %}
{% load i18n %} {% load i18n %}
{% extends 'public/base.html' %}
{% block page_title %}Registration{% endblock %} {% block page_title %}Registration{% endblock %}
{% block extra_include %} {% block extra_include %}
{% include 'bundles/bootstrap-css.html' %} {% include 'bundles/bootstrap-css.html' %}

View File

@@ -69,33 +69,33 @@ class TestCaseWithTestData(TestCase):
# user 1 - corp and alliance, normal user # user 1 - corp and alliance, normal user
character_1 = EveCharacter.objects.create( character_1 = EveCharacter.objects.create(
character_id='1001', character_id=1001,
character_name='Bruce Wayne', character_name='Bruce Wayne',
corporation_id='2001', corporation_id=2001,
corporation_name='Wayne Technologies', corporation_name='Wayne Technologies',
corporation_ticker='WT', corporation_ticker='WT',
alliance_id='3001', alliance_id=3001,
alliance_name='Wayne Enterprises', alliance_name='Wayne Enterprises',
alliance_ticker='WE', alliance_ticker='WE',
) )
character_1a = EveCharacter.objects.create( character_1a = EveCharacter.objects.create(
character_id='1002', character_id=1002,
character_name='Batman', character_name='Batman',
corporation_id='2001', corporation_id=2001,
corporation_name='Wayne Technologies', corporation_name='Wayne Technologies',
corporation_ticker='WT', corporation_ticker='WT',
alliance_id='3001', alliance_id=3001,
alliance_name='Wayne Enterprises', alliance_name='Wayne Enterprises',
alliance_ticker='WE', alliance_ticker='WE',
) )
alliance = EveAllianceInfo.objects.create( alliance = EveAllianceInfo.objects.create(
alliance_id='3001', alliance_id=3001,
alliance_name='Wayne Enterprises', alliance_name='Wayne Enterprises',
alliance_ticker='WE', alliance_ticker='WE',
executor_corp_id='2001' executor_corp_id=2001
) )
EveCorporationInfo.objects.create( EveCorporationInfo.objects.create(
corporation_id='2001', corporation_id=2001,
corporation_name='Wayne Technologies', corporation_name='Wayne Technologies',
corporation_ticker='WT', corporation_ticker='WT',
member_count=42, member_count=42,
@@ -169,10 +169,10 @@ class TestCaseWithTestData(TestCase):
alliance=None alliance=None
) )
EveAllianceInfo.objects.create( EveAllianceInfo.objects.create(
alliance_id='3101', alliance_id=3101,
alliance_name='Lex World Domination', alliance_name='Lex World Domination',
alliance_ticker='LWD', alliance_ticker='LWD',
executor_corp_id='' executor_corp_id=2101
) )
cls.user_3 = User.objects.create_user( cls.user_3 = User.objects.create_user(
character_3.character_name.replace(' ', '_'), character_3.character_name.replace(' ', '_'),
@@ -510,8 +510,8 @@ class TestUserAdmin(TestCaseWithTestData):
filters = changelist.get_filters(request) filters = changelist.get_filters(request)
filterspec = filters[0][0] filterspec = filters[0][0]
expected = [ expected = [
('2002', 'Daily Planet'), (2002, 'Daily Planet'),
('2001', 'Wayne Technologies'), (2001, 'Wayne Technologies'),
] ]
self.assertEqual(filterspec.lookup_choices, expected) self.assertEqual(filterspec.lookup_choices, expected)
@@ -540,7 +540,7 @@ class TestUserAdmin(TestCaseWithTestData):
filters = changelist.get_filters(request) filters = changelist.get_filters(request)
filterspec = filters[0][0] filterspec = filters[0][0]
expected = [ expected = [
('3001', 'Wayne Enterprises'), (3001, 'Wayne Enterprises'),
] ]
self.assertEqual(filterspec.lookup_choices, expected) self.assertEqual(filterspec.lookup_choices, expected)

View File

@@ -0,0 +1,149 @@
from django.contrib.auth.models import User, Group
from django.test import TestCase
from allianceauth.eveonline.models import EveCharacter
from allianceauth.tests.auth_utils import AuthUtils
from esi.models import Token
from ..backends import StateBackend
from ..models import CharacterOwnership, UserProfile, OwnershipRecord
MODULE_PATH = 'allianceauth.authentication'
PERMISSION_1 = "authentication.add_user"
PERMISSION_2 = "authentication.change_user"
class TestStatePermissions(TestCase):
def setUp(self):
# permissions
self.permission_1 = AuthUtils.get_permission_by_name(PERMISSION_1)
self.permission_2 = AuthUtils.get_permission_by_name(PERMISSION_2)
# group
self.group_1 = Group.objects.create(name="Group 1")
self.group_2 = Group.objects.create(name="Group 2")
# state
self.state_1 = AuthUtils.get_member_state()
self.state_2 = AuthUtils.create_state("Other State", 75)
# user
self.user = AuthUtils.create_user("Bruce Wayne")
self.main = AuthUtils.add_main_character_2(self.user, self.user.username, 123)
def test_user_has_user_permissions(self):
self.user.user_permissions.add(self.permission_1)
user = User.objects.get(pk=self.user.pk)
self.assertTrue(user.has_perm(PERMISSION_1))
def test_user_has_group_permissions(self):
self.group_1.permissions.add(self.permission_1)
self.user.groups.add(self.group_1)
user = User.objects.get(pk=self.user.pk)
self.assertTrue(user.has_perm(PERMISSION_1))
def test_user_has_state_permissions(self):
self.state_1.permissions.add(self.permission_1)
self.state_1.member_characters.add(self.main)
user = User.objects.get(pk=self.user.pk)
self.assertTrue(user.has_perm(PERMISSION_1))
def test_when_user_changes_state_perms_change_accordingly(self):
self.state_1.permissions.add(self.permission_1)
self.state_1.member_characters.add(self.main)
user = User.objects.get(pk=self.user.pk)
self.assertTrue(user.has_perm(PERMISSION_1))
self.state_2.permissions.add(self.permission_2)
self.state_2.member_characters.add(self.main)
self.state_1.member_characters.remove(self.main)
user = User.objects.get(pk=self.user.pk)
self.assertFalse(user.has_perm(PERMISSION_1))
self.assertTrue(user.has_perm(PERMISSION_2))
def test_state_permissions_are_returned_for_current_user_object(self):
# verify state permissions are returns for the current user object
# and not for it's instance in the database, which might be outdated
self.state_1.permissions.add(self.permission_1)
self.state_2.permissions.add(self.permission_2)
self.state_1.member_characters.add(self.main)
user = User.objects.get(pk=self.user.pk)
user.profile.state = self.state_2
self.assertFalse(user.has_perm(PERMISSION_1))
self.assertTrue(user.has_perm(PERMISSION_2))
class TestAuthenticate(TestCase):
@classmethod
def setUpTestData(cls):
cls.main_character = EveCharacter.objects.create(
character_id=1,
character_name='Main Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
cls.alt_character = EveCharacter.objects.create(
character_id=2,
character_name='Alt Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
cls.unclaimed_character = EveCharacter.objects.create(
character_id=3,
character_name='Unclaimed Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
cls.user = AuthUtils.create_user('test_user', disconnect_signals=True)
cls.old_user = AuthUtils.create_user('old_user', disconnect_signals=True)
AuthUtils.disconnect_signals()
CharacterOwnership.objects.create(user=cls.user, character=cls.main_character, owner_hash='1')
CharacterOwnership.objects.create(user=cls.user, character=cls.alt_character, owner_hash='2')
UserProfile.objects.update_or_create(user=cls.user, defaults={'main_character': cls.main_character})
AuthUtils.connect_signals()
def test_authenticate_main_character(self):
t = Token(character_id=self.main_character.character_id, character_owner_hash='1')
user = StateBackend().authenticate(token=t)
self.assertEquals(user, self.user)
def test_authenticate_alt_character(self):
t = Token(character_id=self.alt_character.character_id, character_owner_hash='2')
user = StateBackend().authenticate(token=t)
self.assertEquals(user, self.user)
def test_authenticate_unclaimed_character(self):
t = Token(character_id=self.unclaimed_character.character_id, character_name=self.unclaimed_character.character_name, character_owner_hash='3')
user = StateBackend().authenticate(token=t)
self.assertNotEqual(user, self.user)
self.assertEqual(user.username, 'Unclaimed_Character')
self.assertEqual(user.profile.main_character, self.unclaimed_character)
def test_authenticate_character_record(self):
t = Token(character_id=self.unclaimed_character.character_id, character_name=self.unclaimed_character.character_name, character_owner_hash='4')
OwnershipRecord.objects.create(user=self.old_user, character=self.unclaimed_character, owner_hash='4')
user = StateBackend().authenticate(token=t)
self.assertEqual(user, self.old_user)
self.assertTrue(CharacterOwnership.objects.filter(owner_hash='4', user=self.old_user).exists())
self.assertTrue(user.profile.main_character)
def test_iterate_username(self):
t = Token(character_id=self.unclaimed_character.character_id,
character_name=self.unclaimed_character.character_name, character_owner_hash='3')
username = StateBackend().authenticate(token=t).username
t.character_owner_hash = '4'
username_1 = StateBackend().authenticate(token=t).username
t.character_owner_hash = '5'
username_2 = StateBackend().authenticate(token=t).username
self.assertNotEqual(username, username_1, username_2)
self.assertTrue(username_1.endswith('_1'))
self.assertTrue(username_2.endswith('_2'))

View File

@@ -0,0 +1,35 @@
from io import StringIO
from django.core.management import call_command
from django.test import TestCase
from allianceauth.tests.auth_utils import AuthUtils
from ..models import CharacterOwnership, UserProfile
class ManagementCommandTestCase(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = AuthUtils.create_user('test user', disconnect_signals=True)
AuthUtils.add_main_character(cls.user, 'test character', '1', '2', 'test corp', 'test')
character = UserProfile.objects.get(user=cls.user).main_character
CharacterOwnership.objects.create(user=cls.user, character=character, owner_hash='test')
def setUp(self):
self.stdout = StringIO()
def test_ownership(self):
call_command('checkmains', stdout=self.stdout)
self.assertFalse(UserProfile.objects.filter(main_character__isnull=True).count())
self.assertNotIn(self.user.username, self.stdout.getvalue())
self.assertIn('All main characters', self.stdout.getvalue())
def test_no_ownership(self):
user = AuthUtils.create_user('v1 user', disconnect_signals=True)
AuthUtils.add_main_character(user, 'v1 character', '10', '20', 'test corp', 'test')
self.assertFalse(UserProfile.objects.filter(main_character__isnull=True).count())
call_command('checkmains', stdout=self.stdout)
self.assertEqual(UserProfile.objects.filter(main_character__isnull=True).count(), 1)
self.assertIn(user.username, self.stdout.getvalue())

View File

@@ -0,0 +1,68 @@
from unittest import mock
from urllib import parse
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.http.response import HttpResponse
from django.shortcuts import reverse
from django.test import TestCase
from django.test.client import RequestFactory
from allianceauth.eveonline.models import EveCharacter
from allianceauth.tests.auth_utils import AuthUtils
from ..decorators import main_character_required
from ..models import CharacterOwnership
MODULE_PATH = 'allianceauth.authentication'
class DecoratorTestCase(TestCase):
@staticmethod
@main_character_required
def dummy_view(*args, **kwargs):
return HttpResponse(status=200)
@classmethod
def setUpTestData(cls):
cls.main_user = AuthUtils.create_user('main_user', disconnect_signals=True)
cls.no_main_user = AuthUtils.create_user(
'no_main_user', disconnect_signals=True
)
main_character = EveCharacter.objects.create(
character_id=1,
character_name='Main Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
CharacterOwnership.objects.create(
user=cls.main_user, character=main_character, owner_hash='1'
)
cls.main_user.profile.main_character = main_character
def setUp(self):
self.request = RequestFactory().get('/test/')
@mock.patch(MODULE_PATH + '.decorators.messages')
def test_login_redirect(self, m):
setattr(self.request, 'user', AnonymousUser())
response = self.dummy_view(self.request)
self.assertEqual(response.status_code, 302)
url = getattr(response, 'url', None)
self.assertEqual(parse.urlparse(url).path, reverse(settings.LOGIN_URL))
@mock.patch(MODULE_PATH + '.decorators.messages')
def test_main_character_redirect(self, m):
setattr(self.request, 'user', self.no_main_user)
response = self.dummy_view(self.request)
self.assertEqual(response.status_code, 302)
url = getattr(response, 'url', None)
self.assertEqual(url, reverse('authentication:dashboard'))
@mock.patch(MODULE_PATH + '.decorators.messages')
def test_successful_request(self, m):
setattr(self.request, 'user', self.main_user)
response = self.dummy_view(self.request)
self.assertEqual(response.status_code, 200)

View File

@@ -1,147 +1,20 @@
from unittest import mock from unittest import mock
from io import StringIO
from urllib import parse
from django.conf import settings from django.contrib.auth.models import User
from django.contrib.auth.models import AnonymousUser, User
from django.core.management import call_command
from django.http.response import HttpResponse
from django.shortcuts import reverse
from django.test import TestCase from django.test import TestCase
from django.test.client import RequestFactory
from allianceauth.authentication.decorators import main_character_required
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo,\ from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo,\
EveAllianceInfo EveAllianceInfo
from allianceauth.tests.auth_utils import AuthUtils from allianceauth.tests.auth_utils import AuthUtils
from esi.errors import IncompleteResponseError from esi.errors import IncompleteResponseError
from esi.models import Token from esi.models import Token
from ..backends import StateBackend from ..models import CharacterOwnership, State, get_guest_state
from ..models import CharacterOwnership, UserProfile, State, get_guest_state,\
OwnershipRecord
from ..tasks import check_character_ownership from ..tasks import check_character_ownership
MODULE_PATH = 'allianceauth.authentication' MODULE_PATH = 'allianceauth.authentication'
class DecoratorTestCase(TestCase):
@staticmethod
@main_character_required
def dummy_view(*args, **kwargs):
return HttpResponse(status=200)
@classmethod
def setUpTestData(cls):
cls.main_user = AuthUtils.create_user('main_user', disconnect_signals=True)
cls.no_main_user = AuthUtils.create_user('no_main_user', disconnect_signals=True)
main_character = EveCharacter.objects.create(
character_id=1,
character_name='Main Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
CharacterOwnership.objects.create(user=cls.main_user, character=main_character, owner_hash='1')
cls.main_user.profile.main_character = main_character
def setUp(self):
self.request = RequestFactory().get('/test/')
@mock.patch(MODULE_PATH + '.decorators.messages')
def test_login_redirect(self, m):
setattr(self.request, 'user', AnonymousUser())
response = self.dummy_view(self.request)
self.assertEqual(response.status_code, 302)
url = getattr(response, 'url', None)
self.assertEqual(parse.urlparse(url).path, reverse(settings.LOGIN_URL))
@mock.patch(MODULE_PATH + '.decorators.messages')
def test_main_character_redirect(self, m):
setattr(self.request, 'user', self.no_main_user)
response = self.dummy_view(self.request)
self.assertEqual(response.status_code, 302)
url = getattr(response, 'url', None)
self.assertEqual(url, reverse('authentication:dashboard'))
@mock.patch(MODULE_PATH + '.decorators.messages')
def test_successful_request(self, m):
setattr(self.request, 'user', self.main_user)
response = self.dummy_view(self.request)
self.assertEqual(response.status_code, 200)
class BackendTestCase(TestCase):
@classmethod
def setUpTestData(cls):
cls.main_character = EveCharacter.objects.create(
character_id=1,
character_name='Main Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
cls.alt_character = EveCharacter.objects.create(
character_id=2,
character_name='Alt Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
cls.unclaimed_character = EveCharacter.objects.create(
character_id=3,
character_name='Unclaimed Character',
corporation_id=1,
corporation_name='Corp',
corporation_ticker='CORP',
)
cls.user = AuthUtils.create_user('test_user', disconnect_signals=True)
cls.old_user = AuthUtils.create_user('old_user', disconnect_signals=True)
AuthUtils.disconnect_signals()
CharacterOwnership.objects.create(user=cls.user, character=cls.main_character, owner_hash='1')
CharacterOwnership.objects.create(user=cls.user, character=cls.alt_character, owner_hash='2')
UserProfile.objects.update_or_create(user=cls.user, defaults={'main_character': cls.main_character})
AuthUtils.connect_signals()
def test_authenticate_main_character(self):
t = Token(character_id=self.main_character.character_id, character_owner_hash='1')
user = StateBackend().authenticate(token=t)
self.assertEquals(user, self.user)
def test_authenticate_alt_character(self):
t = Token(character_id=self.alt_character.character_id, character_owner_hash='2')
user = StateBackend().authenticate(token=t)
self.assertEquals(user, self.user)
def test_authenticate_unclaimed_character(self):
t = Token(character_id=self.unclaimed_character.character_id, character_name=self.unclaimed_character.character_name, character_owner_hash='3')
user = StateBackend().authenticate(token=t)
self.assertNotEqual(user, self.user)
self.assertEqual(user.username, 'Unclaimed_Character')
self.assertEqual(user.profile.main_character, self.unclaimed_character)
def test_authenticate_character_record(self):
t = Token(character_id=self.unclaimed_character.character_id, character_name=self.unclaimed_character.character_name, character_owner_hash='4')
record = OwnershipRecord.objects.create(user=self.old_user, character=self.unclaimed_character, owner_hash='4')
user = StateBackend().authenticate(token=t)
self.assertEqual(user, self.old_user)
self.assertTrue(CharacterOwnership.objects.filter(owner_hash='4', user=self.old_user).exists())
self.assertTrue(user.profile.main_character)
def test_iterate_username(self):
t = Token(character_id=self.unclaimed_character.character_id,
character_name=self.unclaimed_character.character_name, character_owner_hash='3')
username = StateBackend().authenticate(token=t).username
t.character_owner_hash = '4'
username_1 = StateBackend().authenticate(token=t).username
t.character_owner_hash = '5'
username_2 = StateBackend().authenticate(token=t).username
self.assertNotEqual(username, username_1, username_2)
self.assertTrue(username_1.endswith('_1'))
self.assertTrue(username_2.endswith('_2'))
class CharacterOwnershipTestCase(TestCase): class CharacterOwnershipTestCase(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@@ -343,10 +216,10 @@ class CharacterOwnershipCheckTestCase(TestCase):
cls.user = AuthUtils.create_user('test_user', disconnect_signals=True) cls.user = AuthUtils.create_user('test_user', disconnect_signals=True)
AuthUtils.add_main_character(cls.user, 'Test Character', '1', corp_id='1', alliance_id='1', AuthUtils.add_main_character(cls.user, 'Test Character', '1', corp_id='1', alliance_id='1',
corp_name='Test Corp', alliance_name='Test Alliance') corp_name='Test Corp', alliance_name='Test Alliance')
cls.character = EveCharacter.objects.get(character_id='1') cls.character = EveCharacter.objects.get(character_id=1)
cls.token = Token.objects.create( cls.token = Token.objects.create(
user=cls.user, user=cls.user,
character_id='1', character_id=1,
character_name='Test', character_name='Test',
character_owner_hash='1', character_owner_hash='1',
) )
@@ -378,30 +251,3 @@ class CharacterOwnershipCheckTestCase(TestCase):
filter.return_value.exists.return_value = False filter.return_value.exists.return_value = False
check_character_ownership(self.ownership) check_character_ownership(self.ownership)
self.assertTrue(filter.return_value.delete.called) self.assertTrue(filter.return_value.delete.called)
class ManagementCommandTestCase(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = AuthUtils.create_user('test user', disconnect_signals=True)
AuthUtils.add_main_character(cls.user, 'test character', '1', '2', 'test corp', 'test')
character = UserProfile.objects.get(user=cls.user).main_character
CharacterOwnership.objects.create(user=cls.user, character=character, owner_hash='test')
def setUp(self):
self.stdout = StringIO()
def test_ownership(self):
call_command('checkmains', stdout=self.stdout)
self.assertFalse(UserProfile.objects.filter(main_character__isnull=True).count())
self.assertNotIn(self.user.username, self.stdout.getvalue())
self.assertIn('All main characters', self.stdout.getvalue())
def test_no_ownership(self):
user = AuthUtils.create_user('v1 user', disconnect_signals=True)
AuthUtils.add_main_character(user, 'v1 character', '10', '20', 'test corp', 'test')
self.assertFalse(UserProfile.objects.filter(main_character__isnull=True).count())
call_command('checkmains', stdout=self.stdout)
self.assertEqual(UserProfile.objects.filter(main_character__isnull=True).count(), 1)
self.assertIn(user.username, self.stdout.getvalue())

View File

@@ -70,30 +70,32 @@ class TestStatusOverviewTag(TestCase):
'notifications': GITHUB_NOTIFICATION_ISSUES[:5] 'notifications': GITHUB_NOTIFICATION_ISSUES[:5]
} }
mock_current_notifications.return_value = notifications mock_current_notifications.return_value = notifications
version_info = { version_info = {
'latest_major': True, 'latest_major': True,
'latest_minor': True, 'latest_minor': True,
'latest_patch': True, 'latest_patch': True,
'latest_beta': False,
'current_version': TEST_VERSION, 'current_version': TEST_VERSION,
'latest_major_version': '2.0.0', 'latest_major_version': '2.4.5',
'latest_minor_version': '2.4.0', 'latest_minor_version': '2.4.0',
'latest_patch_version': '2.4.5', 'latest_patch_version': '2.4.5',
'latest_beta_version': '2.4.4a1',
} }
mock_current_version_info.return_value = version_info mock_current_version_info.return_value = version_info
mock_fetch_celery_queue_length.return_value = 3 mock_fetch_celery_queue_length.return_value = 3
context = {} result = status_overview()
result = status_overview(context)
expected = { expected = {
'notifications': GITHUB_NOTIFICATION_ISSUES[:5], 'notifications': GITHUB_NOTIFICATION_ISSUES[:5],
'latest_major': True, 'latest_major': True,
'latest_minor': True, 'latest_minor': True,
'latest_patch': True, 'latest_patch': True,
'latest_beta': False,
'current_version': TEST_VERSION, 'current_version': TEST_VERSION,
'latest_major_version': '2.0.0', 'latest_major_version': '2.4.5',
'latest_minor_version': '2.4.0', 'latest_minor_version': '2.4.0',
'latest_patch_version': '2.4.5', 'latest_patch_version': '2.4.5',
'latest_beta_version': '2.4.4a1',
'task_queue_length': 3, 'task_queue_length': 3,
} }
self.assertEqual(result, expected) self.assertEqual(result, expected)
@@ -125,6 +127,13 @@ class TestNotifications(TestCase):
result = _current_notifications() result = _current_notifications()
self.assertEqual(result['notifications'], list()) self.assertEqual(result['notifications'], list())
@patch(MODULE_PATH + '.admin_status.cache')
def test_current_notifications_is_none(self, mock_cache):
mock_cache.get_or_set.return_value = None
result = _current_notifications()
self.assertEqual(result['notifications'], list())
class TestCeleryQueueLength(TestCase): class TestCeleryQueueLength(TestCase):
@@ -146,6 +155,7 @@ class TestVersionTags(TestCase):
self.assertEqual(result['latest_major_version'], '2.0.0') self.assertEqual(result['latest_major_version'], '2.0.0')
self.assertEqual(result['latest_minor_version'], '2.4.0') self.assertEqual(result['latest_minor_version'], '2.4.0')
self.assertEqual(result['latest_patch_version'], '2.4.5') self.assertEqual(result['latest_patch_version'], '2.4.5')
self.assertEqual(result['latest_beta_version'], '2.4.6a1')
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION) @patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
@patch(MODULE_PATH + '.admin_status.cache') @patch(MODULE_PATH + '.admin_status.cache')
@@ -166,6 +176,15 @@ class TestVersionTags(TestCase):
result = _fetch_tags_from_gitlab() result = _fetch_tags_from_gitlab()
self.assertEqual(result, GITHUB_TAGS) self.assertEqual(result, GITHUB_TAGS)
@patch(MODULE_PATH + '.admin_status.__version__', TEST_VERSION)
@patch(MODULE_PATH + '.admin_status.cache')
def test_current_version_info_return_no_data(self, mock_cache):
mock_cache.get_or_set.return_value = None
expected = {}
result = _current_version_summary()
self.assertEqual(result, expected)
class TestLatestsVersion(TestCase): class TestLatestsVersion(TestCase):
@@ -174,30 +193,33 @@ class TestLatestsVersion(TestCase):
tags = create_tags_list( tags = create_tags_list(
['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0'] ['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0']
) )
major, minor, patch = _latests_versions(tags) major, minor, patch, beta = _latests_versions(tags)
self.assertEqual(major, Pep440Version('2.0.0')) self.assertEqual(major, Pep440Version('2.0.0'))
self.assertEqual(minor, Pep440Version('2.1.0')) self.assertEqual(minor, Pep440Version('2.1.0'))
self.assertEqual(patch, Pep440Version('2.1.1')) self.assertEqual(patch, Pep440Version('2.1.1'))
self.assertEqual(beta, Pep440Version('2.1.1a1'))
def test_major_and_minor_not_defined_with_zero(self): def test_major_and_minor_not_defined_with_zero(self):
tags = create_tags_list( tags = create_tags_list(
['2.1.2', '2.1.1', '2.0.1', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0'] ['2.1.2', '2.1.1', '2.0.1', '2.1.1a1', '1.1.1', '1.1.0', '1.0.0']
) )
major, minor, patch = _latests_versions(tags) major, minor, patch, beta = _latests_versions(tags)
self.assertEqual(major, Pep440Version('2.0.1')) self.assertEqual(major, Pep440Version('2.0.1'))
self.assertEqual(minor, Pep440Version('2.1.1')) self.assertEqual(minor, Pep440Version('2.1.1'))
self.assertEqual(patch, Pep440Version('2.1.2')) self.assertEqual(patch, Pep440Version('2.1.2'))
self.assertEqual(beta, Pep440Version('2.1.1a1'))
def test_can_ignore_invalid_versions(self): def test_can_ignore_invalid_versions(self):
tags = create_tags_list( tags = create_tags_list(
['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', 'invalid'] ['2.1.1', '2.1.0', '2.0.0', '2.1.1a1', 'invalid']
) )
major, minor, patch = _latests_versions(tags) major, minor, patch, beta = _latests_versions(tags)
self.assertEqual(major, Pep440Version('2.0.0')) self.assertEqual(major, Pep440Version('2.0.0'))
self.assertEqual(minor, Pep440Version('2.1.0')) self.assertEqual(minor, Pep440Version('2.1.0'))
self.assertEqual(patch, Pep440Version('2.1.1')) self.assertEqual(patch, Pep440Version('2.1.1'))
self.assertEqual(beta, Pep440Version('2.1.1a1'))
class TestFetchListFromGitlab(TestCase): class TestFetchListFromGitlab(TestCase):

View File

@@ -6,7 +6,7 @@ from django.contrib.auth import login, authenticate
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core import signing from django.core import signing
from django.urls import reverse from django.urls import reverse, reverse_lazy
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@@ -14,12 +14,12 @@ from allianceauth.eveonline.models import EveCharacter
from esi.decorators import token_required from esi.decorators import token_required
from esi.models import Token from esi.models import Token
from registration.backends.hmac.views import ( from django_registration.backends.activation.views import (
RegistrationView as BaseRegistrationView, RegistrationView as BaseRegistrationView,
ActivationView as BaseActivationView, ActivationView as BaseActivationView,
REGISTRATION_SALT REGISTRATION_SALT
) )
from registration.signals import user_registered from django_registration.signals import user_registered
from .models import CharacterOwnership from .models import CharacterOwnership
from .forms import RegistrationForm from .forms import RegistrationForm
@@ -134,11 +134,14 @@ def sso_login(request, token):
# Step 2 # Step 2
class RegistrationView(BaseRegistrationView): class RegistrationView(BaseRegistrationView):
form_class = RegistrationForm form_class = RegistrationForm
success_url = 'authentication:dashboard' template_name = "public/register.html"
email_body_template = "registration/activation_email.txt"
email_subject_template = "registration/activation_email_subject.txt"
success_url = reverse_lazy('registration_complete')
def get_success_url(self, user): def get_success_url(self, user):
if not getattr(settings, 'REGISTRATION_VERIFY_EMAIL', True): if not getattr(settings, 'REGISTRATION_VERIFY_EMAIL', True):
return 'authentication:dashboard', (), {} return reverse_lazy('authentication:dashboard')
return super().get_success_url(user) return super().get_success_url(user)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
@@ -176,6 +179,9 @@ class RegistrationView(BaseRegistrationView):
# Step 3 # Step 3
class ActivationView(BaseActivationView): class ActivationView(BaseActivationView):
template_name = "registration/activate.html"
success_url = reverse_lazy('registration_activation_complete')
def validate_key(self, activation_key): def validate_key(self, activation_key):
try: try:
dump = signing.loads(activation_key, salt=REGISTRATION_SALT, dump = signing.loads(activation_key, salt=REGISTRATION_SALT,
@@ -207,5 +213,5 @@ def activation_complete(request):
def registration_closed(request): def registration_closed(request):
messages.error(request, _('Registraion of new accounts it not allowed at this time.')) messages.error(request, _('Registration of new accounts is not allowed at this time.'))
return redirect('authentication:login') return redirect('authentication:login')

View File

@@ -8,7 +8,7 @@ class CorpStats(MenuItemHook):
def __init__(self): def __init__(self):
MenuItemHook.__init__(self, MenuItemHook.__init__(self,
_('Corporation Stats'), _('Corporation Stats'),
'fa fa-share-alt fa-fw', 'fas fa-share-alt fa-fw',
'corputils:view', 'corputils:view',
navactive=['corputils:']) navactive=['corputils:'])

View File

@@ -17,9 +17,9 @@ class CorpStatsManagerTestCase(TestCase):
cls.user = AuthUtils.create_user('test') cls.user = AuthUtils.create_user('test')
AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST') AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST')
cls.user.profile.refresh_from_db() cls.user.profile.refresh_from_db()
cls.alliance = EveAllianceInfo.objects.create(alliance_id='3', alliance_name='test alliance', alliance_ticker='TEST', executor_corp_id='2') cls.alliance = EveAllianceInfo.objects.create(alliance_id=3, alliance_name='test alliance', alliance_ticker='TEST', executor_corp_id=2)
cls.corp = EveCorporationInfo.objects.create(corporation_id='2', corporation_name='test corp', corporation_ticker='TEST', alliance=cls.alliance, member_count=1) cls.corp = EveCorporationInfo.objects.create(corporation_id=2, corporation_name='test corp', corporation_ticker='TEST', alliance=cls.alliance, member_count=1)
cls.token = Token.objects.create(user=cls.user, access_token='a', character_id='1', character_name='test character', character_owner_hash='z') cls.token = Token.objects.create(user=cls.user, access_token='a', character_id=1, character_name='test character', character_owner_hash='z')
cls.corpstats = CorpStats.objects.create(corp=cls.corp, token=cls.token) cls.corpstats = CorpStats.objects.create(corp=cls.corp, token=cls.token)
cls.view_corp_permission = Permission.objects.get_by_natural_key('view_corp_corpstats', 'corputils', 'corpstats') cls.view_corp_permission = Permission.objects.get_by_natural_key('view_corp_corpstats', 'corputils', 'corpstats')
cls.view_alliance_permission = Permission.objects.get_by_natural_key('view_alliance_corpstats', 'corputils', 'corpstats') cls.view_alliance_permission = Permission.objects.get_by_natural_key('view_alliance_corpstats', 'corputils', 'corpstats')
@@ -66,9 +66,9 @@ class CorpStatsUpdateTestCase(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
cls.user = AuthUtils.create_user('test') cls.user = AuthUtils.create_user('test')
AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST') AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id=2, corp_name='test_corp', corp_ticker='TEST', alliance_id=3, alliance_name='TEST')
cls.token = Token.objects.create(user=cls.user, access_token='a', character_id='1', character_name='test character', character_owner_hash='z') cls.token = Token.objects.create(user=cls.user, access_token='a', character_id=1, character_name='test character', character_owner_hash='z')
cls.corp = EveCorporationInfo.objects.create(corporation_id='2', corporation_name='test corp', corporation_ticker='TEST', member_count=1) cls.corp = EveCorporationInfo.objects.create(corporation_id=2, corporation_name='test corp', corporation_ticker='TEST', member_count=1)
def setUp(self): def setUp(self):
self.corpstats = CorpStats.objects.get_or_create(token=self.token, corp=self.corp)[0] self.corpstats = CorpStats.objects.get_or_create(token=self.token, corp=self.corp)[0]
@@ -88,11 +88,11 @@ class CorpStatsUpdateTestCase(TestCase):
SwaggerClient.from_spec.return_value.Corporation.get_corporations_corporation_id_members.return_value.result.return_value = [1] SwaggerClient.from_spec.return_value.Corporation.get_corporations_corporation_id_members.return_value.result.return_value = [1]
SwaggerClient.from_spec.return_value.Universe.post_universe_names.return_value.result.return_value = [{'id': 1, 'name': 'test character'}] SwaggerClient.from_spec.return_value.Universe.post_universe_names.return_value.result.return_value = [{'id': 1, 'name': 'test character'}]
self.corpstats.update() self.corpstats.update()
self.assertTrue(CorpMember.objects.filter(character_id='1', character_name='test character', corpstats=self.corpstats).exists()) self.assertTrue(CorpMember.objects.filter(character_id=1, character_name='test character', corpstats=self.corpstats).exists())
@mock.patch('esi.clients.SwaggerClient') @mock.patch('esi.clients.SwaggerClient')
def test_update_remove_member(self, SwaggerClient): def test_update_remove_member(self, SwaggerClient):
CorpMember.objects.create(character_id='2', character_name='old test character', corpstats=self.corpstats) CorpMember.objects.create(character_id=2, character_name='old test character', corpstats=self.corpstats)
SwaggerClient.from_spec.return_value.Character.get_characters_character_id.return_value.result.return_value = {'corporation_id': 2} SwaggerClient.from_spec.return_value.Character.get_characters_character_id.return_value.result.return_value = {'corporation_id': 2}
SwaggerClient.from_spec.return_value.Corporation.get_corporations_corporation_id_members.return_value.result.return_value = [1] SwaggerClient.from_spec.return_value.Corporation.get_corporations_corporation_id_members.return_value.result.return_value = [1]
SwaggerClient.from_spec.return_value.Universe.post_universe_names.return_value.result.return_value = [{'id': 1, 'name': 'test character'}] SwaggerClient.from_spec.return_value.Universe.post_universe_names.return_value.result.return_value = [{'id': 1, 'name': 'test character'}]
@@ -130,15 +130,15 @@ class CorpStatsPropertiesTestCase(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
cls.user = AuthUtils.create_user('test') cls.user = AuthUtils.create_user('test')
AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST') AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id=2, corp_name='test_corp', corp_ticker='TEST', alliance_id=3, alliance_name='TEST')
cls.user.profile.refresh_from_db() cls.user.profile.refresh_from_db()
cls.token = Token.objects.create(user=cls.user, access_token='a', character_id='1', character_name='test character', character_owner_hash='z') cls.token = Token.objects.create(user=cls.user, access_token='a', character_id=1, character_name='test character', character_owner_hash='z')
cls.corp = EveCorporationInfo.objects.create(corporation_id='2', corporation_name='test corp', corporation_ticker='TEST', member_count=1) cls.corp = EveCorporationInfo.objects.create(corporation_id=2, corporation_name='test corp', corporation_ticker='TEST', member_count=1)
cls.corpstats = CorpStats.objects.create(token=cls.token, corp=cls.corp) cls.corpstats = CorpStats.objects.create(token=cls.token, corp=cls.corp)
cls.character = EveCharacter.objects.create(character_name='another test character', character_id='4', corporation_id='2', corporation_name='test corp', corporation_ticker='TEST') cls.character = EveCharacter.objects.create(character_name='another test character', character_id=4, corporation_id=2, corporation_name='test corp', corporation_ticker='TEST')
def test_member_count(self): def test_member_count(self):
member = CorpMember.objects.create(corpstats=self.corpstats, character_id='1', character_name='test character') member = CorpMember.objects.create(corpstats=self.corpstats, character_id=2, character_name='test character')
self.assertEqual(self.corpstats.member_count, 1) self.assertEqual(self.corpstats.member_count, 1)
member.delete() member.delete()
self.assertEqual(self.corpstats.member_count, 0) self.assertEqual(self.corpstats.member_count, 0)
@@ -147,7 +147,7 @@ class CorpStatsPropertiesTestCase(TestCase):
AuthUtils.disconnect_signals() AuthUtils.disconnect_signals()
co = CharacterOwnership.objects.create(character=self.character, user=self.user, owner_hash='a') co = CharacterOwnership.objects.create(character=self.character, user=self.user, owner_hash='a')
AuthUtils.connect_signals() AuthUtils.connect_signals()
CorpMember.objects.create(corpstats=self.corpstats, character_id='4', character_name='test character') CorpMember.objects.create(corpstats=self.corpstats, character_id=4, character_name='test character')
self.assertEqual(self.corpstats.user_count, 1) self.assertEqual(self.corpstats.user_count, 1)
co.delete() co.delete()
self.assertEqual(self.corpstats.user_count, 0) self.assertEqual(self.corpstats.user_count, 0)
@@ -156,7 +156,8 @@ class CorpStatsPropertiesTestCase(TestCase):
AuthUtils.disconnect_signals() AuthUtils.disconnect_signals()
co = CharacterOwnership.objects.create(character=self.character, user=self.user, owner_hash='a') co = CharacterOwnership.objects.create(character=self.character, user=self.user, owner_hash='a')
AuthUtils.connect_signals() AuthUtils.connect_signals()
member = CorpMember.objects.create(corpstats=self.corpstats, character_id='4', character_name='test character') member = CorpMember.objects.create(corpstats=self.corpstats, character_id=4, character_name='test character')
self.corpstats.refresh_from_db()
self.assertIn(member, self.corpstats.registered_members) self.assertIn(member, self.corpstats.registered_members)
self.assertEqual(self.corpstats.registered_member_count, 1) self.assertEqual(self.corpstats.registered_member_count, 1)
@@ -165,7 +166,7 @@ class CorpStatsPropertiesTestCase(TestCase):
self.assertEqual(self.corpstats.registered_member_count, 0) self.assertEqual(self.corpstats.registered_member_count, 0)
def test_unregistered_members(self): def test_unregistered_members(self):
member = CorpMember.objects.create(corpstats=self.corpstats, character_id='4', character_name='test character') member = CorpMember.objects.create(corpstats=self.corpstats, character_id=4, character_name='test character')
self.corpstats.refresh_from_db() self.corpstats.refresh_from_db()
self.assertIn(member, self.corpstats.unregistered_members) self.assertIn(member, self.corpstats.unregistered_members)
self.assertEqual(self.corpstats.unregistered_member_count, 1) self.assertEqual(self.corpstats.unregistered_member_count, 1)
@@ -178,13 +179,13 @@ class CorpStatsPropertiesTestCase(TestCase):
def test_mains(self): def test_mains(self):
# test when is a main # test when is a main
member = CorpMember.objects.create(corpstats=self.corpstats, character_id='1', character_name='test character') member = CorpMember.objects.create(corpstats=self.corpstats, character_id=1, character_name='test character')
self.assertIn(member, self.corpstats.mains) self.assertIn(member, self.corpstats.mains)
self.assertEqual(self.corpstats.main_count, 1) self.assertEqual(self.corpstats.main_count, 1)
# test when is an alt # test when is an alt
old_main = self.user.profile.main_character old_main = self.user.profile.main_character
character = EveCharacter.objects.create(character_name='other character', character_id=10, corporation_name='test corp', corporation_id='2', corporation_ticker='TEST') character = EveCharacter.objects.create(character_name='other character', character_id=10, corporation_name='test corp', corporation_id=2, corporation_ticker='TEST')
AuthUtils.disconnect_signals() AuthUtils.disconnect_signals()
co = CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b') co = CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b')
self.user.profile.main_character = character self.user.profile.main_character = character
@@ -208,7 +209,7 @@ class CorpStatsPropertiesTestCase(TestCase):
self.assertEqual(self.corpstats.corp_logo(size=128), 'https://images.evetech.net/corporations/2/logo?size=128') self.assertEqual(self.corpstats.corp_logo(size=128), 'https://images.evetech.net/corporations/2/logo?size=128')
self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://images.evetech.net/alliances/1/logo?size=128') self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://images.evetech.net/alliances/1/logo?size=128')
alliance = EveAllianceInfo.objects.create(alliance_name='test alliance', alliance_id='3', alliance_ticker='TEST', executor_corp_id='2') alliance = EveAllianceInfo.objects.create(alliance_name='test alliance', alliance_id=3, alliance_ticker='TEST', executor_corp_id=2)
self.corp.alliance = alliance self.corp.alliance = alliance
self.corp.save() self.corp.save()
self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://images.evetech.net/alliances/3/logo?size=128') self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://images.evetech.net/alliances/3/logo?size=128')
@@ -221,14 +222,14 @@ class CorpMemberTestCase(TestCase):
cls.user = AuthUtils.create_user('test') cls.user = AuthUtils.create_user('test')
AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST') AuthUtils.add_main_character(cls.user, 'test character', '1', corp_id='2', corp_name='test_corp', corp_ticker='TEST', alliance_id='3', alliance_name='TEST')
cls.user.profile.refresh_from_db() cls.user.profile.refresh_from_db()
cls.token = Token.objects.create(user=cls.user, access_token='a', character_id='1', character_name='test character', character_owner_hash='a') cls.token = Token.objects.create(user=cls.user, access_token='a', character_id=1, character_name='test character', character_owner_hash='a')
cls.corp = EveCorporationInfo.objects.create(corporation_id='2', corporation_name='test corp', corporation_ticker='TEST', member_count=1) cls.corp = EveCorporationInfo.objects.create(corporation_id=2, corporation_name='test corp', corporation_ticker='TEST', member_count=1)
cls.corpstats = CorpStats.objects.create(token=cls.token, corp=cls.corp) cls.corpstats = CorpStats.objects.create(token=cls.token, corp=cls.corp)
cls.member = CorpMember.objects.create(corpstats=cls.corpstats, character_id='2', character_name='other test character') cls.member = CorpMember.objects.create(corpstats=cls.corpstats, character_id=2, character_name='other test character')
def test_character(self): def test_character(self):
self.assertIsNone(self.member.character) self.assertIsNone(self.member.character)
character = EveCharacter.objects.create(character_id='2', character_name='other test character', corporation_id='2', corporation_name='test corp', corporation_ticker='TEST') character = EveCharacter.objects.create(character_id=2, character_name='other test character', corporation_id=2, corporation_name='test corp', corporation_ticker='TEST')
self.assertEqual(self.member.character, character) self.assertEqual(self.member.character, character)
def test_main_character(self): def test_main_character(self):
@@ -238,7 +239,7 @@ class CorpMemberTestCase(TestCase):
self.assertIsNone(self.member.main_character) self.assertIsNone(self.member.main_character)
# test when member.character is not None but also not a main # test when member.character is not None but also not a main
character = EveCharacter.objects.create(character_id='2', character_name='other test character', corporation_id='2', corporation_name='test corp', corporation_ticker='TEST') character = EveCharacter.objects.create(character_id=2, character_name='other test character', corporation_id=2, corporation_name='test corp', corporation_ticker='TEST')
CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b') CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b')
self.member.refresh_from_db() self.member.refresh_from_db()
self.assertNotEqual(self.member.main_character, self.member.character) self.assertNotEqual(self.member.main_character, self.member.character)
@@ -260,14 +261,14 @@ class CorpMemberTestCase(TestCase):
def test_alts(self): def test_alts(self):
self.assertListEqual(self.member.alts, []) self.assertListEqual(self.member.alts, [])
character = EveCharacter.objects.create(character_id='2', character_name='other test character', corporation_id='2', corporation_name='test corp', corporation_ticker='TEST') character = EveCharacter.objects.create(character_id=2, character_name='other test character', corporation_id=2, corporation_name='test corp', corporation_ticker='TEST')
CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b') CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b')
self.assertIn(character, self.member.alts) self.assertIn(character, self.member.alts)
def test_registered(self): def test_registered(self):
self.assertFalse(self.member.registered) self.assertFalse(self.member.registered)
AuthUtils.disconnect_signals() AuthUtils.disconnect_signals()
character = EveCharacter.objects.create(character_id='2', character_name='other test character', corporation_id='2', corporation_name='test corp', corporation_ticker='TEST') character = EveCharacter.objects.create(character_id=2, character_name='other test character', corporation_id=2, corporation_name='test corp', corporation_ticker='TEST')
CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b') CharacterOwnership.objects.create(character=character, user=self.user, owner_hash='b')
self.assertTrue(self.member.registered) self.assertTrue(self.member.registered)
AuthUtils.connect_signals() AuthUtils.connect_signals()

View File

@@ -0,0 +1,43 @@
# Generated by Django 2.2.12 on 2020-05-25 02:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('eveonline', '0010_alliance_ticker'),
]
operations = [
migrations.AlterField(
model_name='eveallianceinfo',
name='alliance_id',
field=models.PositiveIntegerField(unique=True),
),
migrations.AlterField(
model_name='eveallianceinfo',
name='executor_corp_id',
field=models.PositiveIntegerField(),
),
migrations.AlterField(
model_name='evecharacter',
name='alliance_id',
field=models.PositiveIntegerField(blank=True, default=None, null=True),
),
migrations.AlterField(
model_name='evecharacter',
name='character_id',
field=models.PositiveIntegerField(unique=True),
),
migrations.AlterField(
model_name='evecharacter',
name='corporation_id',
field=models.PositiveIntegerField(),
),
migrations.AlterField(
model_name='evecorporationinfo',
name='corporation_id',
field=models.PositiveIntegerField(unique=True),
),
]

View File

@@ -0,0 +1,33 @@
# Generated by Django 2.2.12 on 2020-05-26 02:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('eveonline', '0011_ids_to_integers'),
]
operations = [
migrations.AddIndex(
model_name='eveallianceinfo',
index=models.Index(fields=['executor_corp_id'], name='eveonline_e_executo_7f3280_idx'),
),
migrations.AddIndex(
model_name='evecharacter',
index=models.Index(fields=['corporation_id'], name='eveonline_e_corpora_cb4cd9_idx'),
),
migrations.AddIndex(
model_name='evecharacter',
index=models.Index(fields=['alliance_id'], name='eveonline_e_allianc_39ee2a_idx'),
),
migrations.AddIndex(
model_name='evecharacter',
index=models.Index(fields=['corporation_name'], name='eveonline_e_corpora_893c60_idx'),
),
migrations.AddIndex(
model_name='evecharacter',
index=models.Index(fields=['alliance_name'], name='eveonline_e_allianc_63fd98_idx'),
),
]

View File

@@ -11,14 +11,17 @@ _DEFAULT_IMAGE_SIZE = 32
class EveAllianceInfo(models.Model): class EveAllianceInfo(models.Model):
alliance_id = models.CharField(max_length=254, unique=True) alliance_id = models.PositiveIntegerField(unique=True)
alliance_name = models.CharField(max_length=254, unique=True) alliance_name = models.CharField(max_length=254, unique=True)
alliance_ticker = models.CharField(max_length=254) alliance_ticker = models.CharField(max_length=254)
executor_corp_id = models.CharField(max_length=254) executor_corp_id = models.PositiveIntegerField()
objects = EveAllianceManager() objects = EveAllianceManager()
provider = EveAllianceProviderManager() provider = EveAllianceProviderManager()
class Meta:
indexes = [models.Index(fields=['executor_corp_id',])]
def populate_alliance(self): def populate_alliance(self):
alliance = self.provider.get_alliance(self.alliance_id) alliance = self.provider.get_alliance(self.alliance_id)
for corp_id in alliance.corp_ids: for corp_id in alliance.corp_ids:
@@ -75,7 +78,7 @@ class EveAllianceInfo(models.Model):
class EveCorporationInfo(models.Model): class EveCorporationInfo(models.Model):
corporation_id = models.CharField(max_length=254, unique=True) corporation_id = models.PositiveIntegerField(unique=True)
corporation_name = models.CharField(max_length=254, unique=True) corporation_name = models.CharField(max_length=254, unique=True)
corporation_ticker = models.CharField(max_length=254) corporation_ticker = models.CharField(max_length=254)
member_count = models.IntegerField() member_count = models.IntegerField()
@@ -133,18 +136,26 @@ class EveCorporationInfo(models.Model):
class EveCharacter(models.Model): class EveCharacter(models.Model):
character_id = models.CharField(max_length=254, unique=True) character_id = models.PositiveIntegerField(unique=True)
character_name = models.CharField(max_length=254, unique=True) character_name = models.CharField(max_length=254, unique=True)
corporation_id = models.CharField(max_length=254) corporation_id = models.PositiveIntegerField()
corporation_name = models.CharField(max_length=254) corporation_name = models.CharField(max_length=254)
corporation_ticker = models.CharField(max_length=5) corporation_ticker = models.CharField(max_length=5)
alliance_id = models.CharField(max_length=254, blank=True, null=True, default='') alliance_id = models.PositiveIntegerField(blank=True, null=True, default=None)
alliance_name = models.CharField(max_length=254, blank=True, null=True, default='') alliance_name = models.CharField(max_length=254, blank=True, null=True, default='')
alliance_ticker = models.CharField(max_length=5, blank=True, null=True, default='') alliance_ticker = models.CharField(max_length=5, blank=True, null=True, default='')
objects = EveCharacterManager() objects = EveCharacterManager()
provider = EveCharacterProviderManager() provider = EveCharacterProviderManager()
class Meta:
indexes = [
models.Index(fields=['corporation_id',]),
models.Index(fields=['alliance_id',]),
models.Index(fields=['corporation_name',]),
models.Index(fields=['alliance_name',]),
]
@property @property
def alliance(self) -> Union[EveAllianceInfo, None]: def alliance(self) -> Union[EveAllianceInfo, None]:
""" """

View File

@@ -7,6 +7,8 @@ from jsonschema.exceptions import RefResolutionError
from django.conf import settings from django.conf import settings
from esi.clients import esi_client_factory from esi.clients import esi_client_factory
from allianceauth import __version__
SWAGGER_SPEC_PATH = os.path.join(os.path.dirname( SWAGGER_SPEC_PATH = os.path.join(os.path.dirname(
os.path.abspath(__file__)), 'swagger.json' os.path.abspath(__file__)), 'swagger.json'
@@ -166,7 +168,7 @@ class EveSwaggerProvider(EveProvider):
else: else:
try: try:
self._client = esi_client_factory( self._client = esi_client_factory(
token=token, spec_file=SWAGGER_SPEC_PATH token=token, spec_file=SWAGGER_SPEC_PATH, app_info_text=("allianceauth v" + __version__)
) )
except (HTTPError, RefResolutionError): except (HTTPError, RefResolutionError):
logger.exception( logger.exception(
@@ -182,7 +184,7 @@ class EveSwaggerProvider(EveProvider):
def client(self): def client(self):
if self._client is None: if self._client is None:
self._client = esi_client_factory( self._client = esi_client_factory(
token=self._token, spec_file=SWAGGER_SPEC_PATH token=self._token, spec_file=SWAGGER_SPEC_PATH, app_info_text=("allianceauth v" + __version__)
) )
return self._client return self._client

View File

@@ -5,35 +5,96 @@ from .models import EveAllianceInfo
from .models import EveCharacter from .models import EveCharacter
from .models import EveCorporationInfo from .models import EveCorporationInfo
from . import providers
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
TASK_PRIORITY = 7 TASK_PRIORITY = 7
CHUNK_SIZE = 500
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
@shared_task @shared_task
def update_corp(corp_id): def update_corp(corp_id):
"""Update given corporation from ESI"""
EveCorporationInfo.objects.update_corporation(corp_id) EveCorporationInfo.objects.update_corporation(corp_id)
@shared_task @shared_task
def update_alliance(alliance_id): def update_alliance(alliance_id):
"""Update given alliance from ESI"""
EveAllianceInfo.objects.update_alliance(alliance_id).populate_alliance() EveAllianceInfo.objects.update_alliance(alliance_id).populate_alliance()
@shared_task @shared_task
def update_character(character_id): def update_character(character_id):
"""Update given character from ESI"""
EveCharacter.objects.update_character(character_id) EveCharacter.objects.update_character(character_id)
@shared_task @shared_task
def run_model_update(): def run_model_update():
"""Update all alliances, corporations and characters from ESI"""
# update existing corp models # update existing corp models
for corp in EveCorporationInfo.objects.all().values('corporation_id'): for corp in EveCorporationInfo.objects.all().values('corporation_id'):
update_corp.apply_async(args=[corp['corporation_id']], priority=TASK_PRIORITY) update_corp.apply_async(
args=[corp['corporation_id']], priority=TASK_PRIORITY
)
# update existing alliance models # update existing alliance models
for alliance in EveAllianceInfo.objects.all().values('alliance_id'): for alliance in EveAllianceInfo.objects.all().values('alliance_id'):
update_alliance.apply_async(args=[alliance['alliance_id']], priority=TASK_PRIORITY) update_alliance.apply_async(
args=[alliance['alliance_id']], priority=TASK_PRIORITY
)
#update existing character models # update existing character models
for character in EveCharacter.objects.all().values('character_id'): character_ids = EveCharacter.objects.all().values_list('character_id', flat=True)
update_character.apply_async(args=[character['character_id']], priority=TASK_PRIORITY) for character_ids_chunk in chunks(character_ids, CHUNK_SIZE):
affiliations_raw = providers.provider.client.Character\
.post_characters_affiliation(characters=character_ids_chunk).result()
character_names = providers.provider.client.Universe\
.post_universe_names(ids=character_ids_chunk).result()
affiliations = {
affiliation.get('character_id'): affiliation
for affiliation in affiliations_raw
}
# add character names to affiliations
for character in character_names:
character_id = character.get('id')
if character_id in affiliations:
affiliations[character_id]['name'] = character.get('name')
# fetch current characters
characters = EveCharacter.objects.filter(character_id__in=character_ids_chunk)\
.values('character_id', 'corporation_id', 'alliance_id', 'character_name')
for character in characters:
character_id = character.get('character_id')
if character_id in affiliations:
affiliation = affiliations[character_id]
corp_changed = (
character.get('corporation_id') != affiliation.get('corporation_id')
)
alliance_id = character.get('alliance_id')
if not alliance_id:
alliance_id = None
alliance_changed = alliance_id != affiliation.get('alliance_id')
name_changed = False
fetched_name = affiliation.get('name', False)
if fetched_name:
name_changed = character.get('character_name') != fetched_name
if corp_changed or alliance_changed or name_changed:
update_character.apply_async(
args=[character.get('character_id')], priority=TASK_PRIORITY
)

View File

@@ -12,7 +12,7 @@ class EveCharacterProviderManagerTestCase(TestCase):
expected = Character() expected = Character()
provider.get_character.return_value = expected provider.get_character.return_value = expected
result = EveCharacter.provider.get_character('1234') result = EveCharacter.provider.get_character(1234)
self.assertEqual(expected, result) self.assertEqual(expected, result)
@@ -22,30 +22,30 @@ class EveCharacterManagerTestCase(TestCase):
class TestCharacter(Character): class TestCharacter(Character):
@property @property
def alliance(self): def alliance(self):
return Alliance(id='3456', name='Test Alliance') return Alliance(id=3456, name='Test Alliance')
@property @property
def corp(self): def corp(self):
return Corporation( return Corporation(
id='2345', id=2345,
name='Test Corp', name='Test Corp',
alliance_id='3456', alliance_id=3456,
ticker='0BUGS' ticker='0BUGS' #lies, blatant lies!
) )
@mock.patch('allianceauth.eveonline.managers.providers.provider') @mock.patch('allianceauth.eveonline.managers.providers.provider')
def test_create_character(self, provider): def test_create_character(self, provider):
# Also covers create_character_obj # Also covers create_character_obj
expected = self.TestCharacter( expected = self.TestCharacter(
id='1234', id=1234,
name='Test Character', name='Test Character',
corp_id='2345', corp_id=2345,
alliance_id='3456' alliance_id=3456
) )
provider.get_character.return_value = expected provider.get_character.return_value = expected
result = EveCharacter.objects.create_character('1234') result = EveCharacter.objects.create_character(1234)
self.assertEqual(result.character_id, expected.id) self.assertEqual(result.character_id, expected.id)
self.assertEqual(result.character_name, expected.name) self.assertEqual(result.character_name, expected.name)
@@ -58,22 +58,25 @@ class EveCharacterManagerTestCase(TestCase):
@mock.patch('allianceauth.eveonline.managers.providers.provider') @mock.patch('allianceauth.eveonline.managers.providers.provider')
def test_update_character(self, provider): def test_update_character(self, provider):
# Also covers Model.update_character # Also covers Model.update_character
EveCharacter.objects.create( existing = EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='character.corp.id', corporation_id=23457,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id='character.alliance.id', alliance_id=34567,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
expected = self.TestCharacter( expected = self.TestCharacter(
id='1234', name='Test Character', corp_id='2345', alliance_id='3456' id=1234,
name='Test Character',
corp_id=2345,
alliance_id=3456
) )
provider.get_character.return_value = expected provider.get_character.return_value = expected
result = EveCharacter.objects.update_character('1234') result = EveCharacter.objects.update_character(1234)
self.assertEqual(result.character_id, expected.id) self.assertEqual(result.character_id, expected.id)
self.assertEqual(result.character_name, expected.name) self.assertEqual(result.character_name, expected.name)
@@ -86,23 +89,23 @@ class EveCharacterManagerTestCase(TestCase):
def test_get_character_by_id(self): def test_get_character_by_id(self):
EveCharacter.objects.all().delete() EveCharacter.objects.all().delete()
EveCharacter.objects.create( EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='character.corp.id', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id='character.alliance.id', alliance_id=3456,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
# try to get existing character # try to get existing character
result = EveCharacter.objects.get_character_by_id('1234') result = EveCharacter.objects.get_character_by_id(1234)
self.assertEqual(result.character_id, '1234') self.assertEqual(result.character_id, 1234)
self.assertEqual(result.character_name, 'character.name') self.assertEqual(result.character_name, 'character.name')
# try to get non existing character # try to get non existing character
self.assertIsNone(EveCharacter.objects.get_character_by_id('9999')) self.assertIsNone(EveCharacter.objects.get_character_by_id(9999))
class EveAllianceProviderManagerTestCase(TestCase): class EveAllianceProviderManagerTestCase(TestCase):
@@ -111,7 +114,7 @@ class EveAllianceProviderManagerTestCase(TestCase):
expected = Alliance() expected = Alliance()
provider.get_alliance.return_value = expected provider.get_alliance.return_value = expected
result = EveAllianceInfo.provider.get_alliance('1234') result = EveAllianceInfo.provider.get_alliance(1234)
self.assertEqual(expected, result) self.assertEqual(expected, result)
@@ -127,16 +130,16 @@ class EveAllianceManagerTestCase(TestCase):
def test_create_alliance(self, provider, populate_alliance): def test_create_alliance(self, provider, populate_alliance):
# Also covers create_alliance_obj # Also covers create_alliance_obj
expected = self.TestAlliance( expected = self.TestAlliance(
id='3456', id=3456,
name='Test Alliance', name='Test Alliance',
ticker='TEST', ticker='TEST',
corp_ids=['2345'], corp_ids=[2345],
executor_corp_id='2345' executor_corp_id=2345
) )
provider.get_alliance.return_value = expected provider.get_alliance.return_value = expected
result = EveAllianceInfo.objects.create_alliance('3456') result = EveAllianceInfo.objects.create_alliance(3456)
self.assertEqual(result.alliance_id, expected.id) self.assertEqual(result.alliance_id, expected.id)
self.assertEqual(result.alliance_name, expected.name) self.assertEqual(result.alliance_name, expected.name)
@@ -148,22 +151,22 @@ class EveAllianceManagerTestCase(TestCase):
def test_update_alliance(self, provider): def test_update_alliance(self, provider):
# Also covers Model.update_alliance # Also covers Model.update_alliance
EveAllianceInfo.objects.create( EveAllianceInfo.objects.create(
alliance_id='3456', alliance_id=3456,
alliance_name='alliance.name', alliance_name='alliance.name',
alliance_ticker='alliance.ticker', alliance_ticker='at1',
executor_corp_id='alliance.executor_corp_id', executor_corp_id=2345,
) )
expected = self.TestAlliance( expected = self.TestAlliance(
id='3456', id=3456,
name='Test Alliance', name='Test Alliance',
ticker='TEST', ticker='TEST',
corp_ids=['2345'], corp_ids=[2345],
executor_corp_id='2345' executor_corp_id=2345
) )
provider.get_alliance.return_value = expected provider.get_alliance.return_value = expected
result = EveAllianceInfo.objects.update_alliance('3456') result = EveAllianceInfo.objects.update_alliance(3456)
# This is the only thing ever updated in code # This is the only thing ever updated in code
self.assertEqual(result.executor_corp_id, expected.executor_corp_id) self.assertEqual(result.executor_corp_id, expected.executor_corp_id)
@@ -175,7 +178,7 @@ class EveCorporationProviderManagerTestCase(TestCase):
expected = Corporation() expected = Corporation()
provider.get_corp.return_value = expected provider.get_corp.return_value = expected
result = EveCorporationInfo.provider.get_corporation('2345') result = EveCorporationInfo.provider.get_corporation(2345)
self.assertEqual(expected, result) self.assertEqual(expected, result)
@@ -186,39 +189,39 @@ class EveCorporationManagerTestCase(TestCase):
@property @property
def alliance(self): def alliance(self):
return EveAllianceManagerTestCase.TestAlliance( return EveAllianceManagerTestCase.TestAlliance(
id='3456', id=3456,
name='Test Alliance', name='Test Alliance',
ticker='TEST', ticker='TEST',
corp_ids=['2345'], corp_ids=[2345],
executor_corp_id='2345' executor_corp_id=2345
) )
@property @property
def ceo(self): def ceo(self):
return EveCharacterManagerTestCase.TestCharacter( return EveCharacterManagerTestCase.TestCharacter(
id='1234', id=1234,
name='Test Character', name='Test Character',
corp_id='2345', corp_id=2345,
alliance_id='3456' alliance_id=3456
) )
@mock.patch('allianceauth.eveonline.managers.providers.provider') @mock.patch('allianceauth.eveonline.managers.providers.provider')
def test_create_corporation(self, provider): def test_create_corporation(self, provider):
# Also covers create_corp_obj # Also covers create_corp_obj
exp_alliance = EveAllianceInfo.objects.create( exp_alliance = EveAllianceInfo.objects.create(
alliance_id='3456', alliance_id=3456,
alliance_name='alliance.name', alliance_name='alliance.name',
alliance_ticker='alliance.ticker', alliance_ticker='99bug',
executor_corp_id='alliance.executor_corp_id', executor_corp_id=2345,
) )
expected = self.TestCorporation( expected = self.TestCorporation(
id='2345', id=2345,
name='Test Corp', name='Test Corp',
ticker='0BUGS', ticker='0BUGS',
ceo_id='1234', ceo_id=1234,
members=1, members=1,
alliance_id='3456' alliance_id=3456
) )
provider.get_corp.return_value = expected provider.get_corp.return_value = expected
@@ -236,17 +239,17 @@ class EveCorporationManagerTestCase(TestCase):
# variant to test no alliance case # variant to test no alliance case
# Also covers create_corp_obj # Also covers create_corp_obj
expected = self.TestCorporation( expected = self.TestCorporation(
id='2345', id=2345,
name='Test Corp', name='Test Corp',
ticker='0BUGS', ticker='0BUGS',
ceo_id='1234', ceo_id=1234,
members=1, members=1,
alliance_id='3456' alliance_id=3456
) )
provider.get_corp.return_value = expected provider.get_corp.return_value = expected
result = EveCorporationInfo.objects.create_corporation('2345') result = EveCorporationInfo.objects.create_corporation(2345)
self.assertEqual(result.corporation_id, expected.id) self.assertEqual(result.corporation_id, expected.id)
self.assertEqual(result.corporation_name, expected.name) self.assertEqual(result.corporation_name, expected.name)
@@ -258,27 +261,27 @@ class EveCorporationManagerTestCase(TestCase):
def test_update_corporation(self, provider): def test_update_corporation(self, provider):
# Also covers Model.update_corporation # Also covers Model.update_corporation
exp_alliance = EveAllianceInfo.objects.create( exp_alliance = EveAllianceInfo.objects.create(
alliance_id='3456', alliance_id=3456,
alliance_name='alliance.name', alliance_name='alliance.name',
alliance_ticker='alliance.ticker', alliance_ticker='at1',
executor_corp_id='alliance.executor_corp_id', executor_corp_id=2345,
) )
EveCorporationInfo.objects.create( EveCorporationInfo.objects.create(
corporation_id='2345', corporation_id=2345,
corporation_name='corp.name', corporation_name='corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
member_count=10, member_count=10,
alliance=None, alliance=None,
) )
expected = self.TestCorporation( expected = self.TestCorporation(
id='2345', id=2345,
name='Test Corp', name='Test Corp',
ticker='0BUGS', ticker='0BUGS',
ceo_id='1234', ceo_id=1234,
members=1, members=1,
alliance_id='3456' alliance_id=3456
) )
provider.get_corp.return_value = expected provider.get_corp.return_value = expected

View File

@@ -15,27 +15,27 @@ class EveCharacterTestCase(TestCase):
Test that the correct corporation is returned by the corporation property Test that the correct corporation is returned by the corporation property
""" """
character = EveCharacter.objects.create( character = EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='2345', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id='character.alliance.id', alliance_id=12345,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
expected = EveCorporationInfo.objects.create( expected = EveCorporationInfo.objects.create(
corporation_id='2345', corporation_id=2345,
corporation_name='corp.name', corporation_name='corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
member_count=10, member_count=10,
alliance=None, alliance=None,
) )
incorrect = EveCorporationInfo.objects.create( incorrect = EveCorporationInfo.objects.create(
corporation_id='9999', corporation_id=9999,
corporation_name='corp.name1', corporation_name='corp.name1',
corporation_ticker='abc1', corporation_ticker='cc11',
member_count=10, member_count=10,
alliance=None, alliance=None,
) )
@@ -49,12 +49,12 @@ class EveCharacterTestCase(TestCase):
object is not in the database object is not in the database
""" """
character = EveCharacter.objects.create( character = EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='2345', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id='character.alliance.id', alliance_id=123456,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
@@ -66,27 +66,27 @@ class EveCharacterTestCase(TestCase):
Test that the correct alliance is returned by the alliance property Test that the correct alliance is returned by the alliance property
""" """
character = EveCharacter.objects.create( character = EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='2345', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id='3456', alliance_id=3456,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
expected = EveAllianceInfo.objects.create( expected = EveAllianceInfo.objects.create(
alliance_id='3456', alliance_id=3456,
alliance_name='alliance.name', alliance_name='alliance.name',
alliance_ticker='alliance.ticker', alliance_ticker='ac2',
executor_corp_id='alliance.executor_corp_id', executor_corp_id=2345,
) )
incorrect = EveAllianceInfo.objects.create( incorrect = EveAllianceInfo.objects.create(
alliance_id='9001', alliance_id=9001,
alliance_name='alliance.name1', alliance_name='alliance.name1',
alliance_ticker='alliance.ticker1', alliance_ticker='ac1',
executor_corp_id='alliance.executor_corp_id1', executor_corp_id=2654,
) )
self.assertEqual(character.alliance, expected) self.assertEqual(character.alliance, expected)
@@ -98,12 +98,12 @@ class EveCharacterTestCase(TestCase):
object is not in the database object is not in the database
""" """
character = EveCharacter.objects.create( character = EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='2345', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id='3456', alliance_id=3456,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
@@ -115,11 +115,11 @@ class EveCharacterTestCase(TestCase):
Check that None is returned when the character has no alliance Check that None is returned when the character has no alliance
""" """
character = EveCharacter.objects.create( character = EveCharacter.objects.create(
character_id='1234', character_id=1234,
character_name='character.name', character_name='character.name',
corporation_id='2345', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='abc', corporation_ticker='cc1',
alliance_id=None, alliance_id=None,
alliance_name=None, alliance_name=None,
) )
@@ -137,12 +137,12 @@ class EveCharacterTestCase(TestCase):
) )
my_character = EveCharacter.objects.create( my_character = EveCharacter.objects.create(
character_id='1001', character_id=1001,
character_name='Bruce Wayne', character_name='Bruce Wayne',
corporation_id='2001', corporation_id=2001,
corporation_name='Dummy Corp 1', corporation_name='Dummy Corp 1',
corporation_ticker='DC1', corporation_ticker='DC1',
alliance_id='3001', alliance_id=3001,
alliance_name='Dummy Alliance 1', alliance_name='Dummy Alliance 1',
) )
my_updated_character = Character( my_updated_character = Character(
@@ -166,9 +166,9 @@ class EveCharacterTestCase(TestCase):
def test_portrait_urls(self): def test_portrait_urls(self):
x = EveCharacter( x = EveCharacter(
character_id='42', character_id=42,
character_name='character.name', character_name='character.name',
corporation_id='123', corporation_id=123,
corporation_name='corporation.name', corporation_name='corporation.name',
corporation_ticker='ABC', corporation_ticker='ABC',
) )
@@ -199,9 +199,9 @@ class EveCharacterTestCase(TestCase):
def test_corporation_logo_urls(self): def test_corporation_logo_urls(self):
x = EveCharacter( x = EveCharacter(
character_id='42', character_id=42,
character_name='character.name', character_name='character.name',
corporation_id='123', corporation_id=123,
corporation_name='corporation.name', corporation_name='corporation.name',
corporation_ticker='ABC', corporation_ticker='ABC',
) )
@@ -232,9 +232,9 @@ class EveCharacterTestCase(TestCase):
def test_alliance_logo_urls(self): def test_alliance_logo_urls(self):
x = EveCharacter( x = EveCharacter(
character_id='42', character_id=42,
character_name='character.name', character_name='character.name',
corporation_id='123', corporation_id=123,
corporation_name='corporation.name', corporation_name='corporation.name',
corporation_ticker='ABC', corporation_ticker='ABC',
) )
@@ -405,10 +405,10 @@ class EveAllianceTestCase(TestCase):
def test_logo_url(self): def test_logo_url(self):
x = EveAllianceInfo( x = EveAllianceInfo(
alliance_id='42', alliance_id=42,
alliance_name='alliance.name', alliance_name='alliance.name',
alliance_ticker='ABC', alliance_ticker='ABC',
executor_corp_id='123' executor_corp_id=123
) )
self.assertEqual( self.assertEqual(
x.logo_url(), x.logo_url(),

View File

@@ -592,3 +592,12 @@ class TestEveSwaggerProvider(TestCase):
self.assertTrue(mock_esi_client_factory.called) self.assertTrue(mock_esi_client_factory.called)
self.assertIsNotNone(my_provider._client) self.assertIsNotNone(my_provider._client)
self.assertEqual(my_client, 'my_client') self.assertEqual(my_client, 'my_client')
@patch(MODULE_PATH + '.__version__', '1.0.0')
def test_user_agent_header(self):
my_provider = EveSwaggerProvider()
my_client = my_provider.client
operation = my_client.Status.get_status()
self.assertEqual(
operation.future.request.headers['User-Agent'], 'allianceauth v1.0.0'
)

View File

@@ -1,4 +1,4 @@
from unittest.mock import patch from unittest.mock import patch, Mock
from django.test import TestCase from django.test import TestCase
@@ -44,55 +44,202 @@ class TestTasks(TestCase):
mock_EveCharacter.objects.update_character.call_args[0][0], 42 mock_EveCharacter.objects.update_character.call_args[0][0], 42
) )
@patch('allianceauth.eveonline.tasks.update_character')
@patch('allianceauth.eveonline.tasks.update_alliance') @patch('allianceauth.eveonline.tasks.update_character')
@patch('allianceauth.eveonline.tasks.update_corp') @patch('allianceauth.eveonline.tasks.update_alliance')
def test_run_model_update( @patch('allianceauth.eveonline.tasks.update_corp')
self, @patch('allianceauth.eveonline.providers.provider')
mock_update_corp, @patch('allianceauth.eveonline.tasks.CHUNK_SIZE', 2)
mock_update_alliance, class TestRunModelUpdate(TestCase):
mock_update_character,
): @classmethod
def setUpClass(cls):
super().setUpClass()
EveCorporationInfo.objects.all().delete() EveCorporationInfo.objects.all().delete()
EveAllianceInfo.objects.all().delete() EveAllianceInfo.objects.all().delete()
EveCharacter.objects.all().delete() EveCharacter.objects.all().delete()
EveCorporationInfo.objects.create( EveCorporationInfo.objects.create(
corporation_id='2345', corporation_id=2345,
corporation_name='corp.name', corporation_name='corp.name',
corporation_ticker='corp.ticker', corporation_ticker='c.c.t',
member_count=10, member_count=10,
alliance=None, alliance=None,
) )
EveAllianceInfo.objects.create( EveAllianceInfo.objects.create(
alliance_id='3456', alliance_id=3456,
alliance_name='alliance.name', alliance_name='alliance.name',
alliance_ticker='alliance.ticker', alliance_ticker='a.t',
executor_corp_id='alliance.executor_corp_id', executor_corp_id=5,
) )
EveCharacter.objects.create( EveCharacter.objects.create(
character_id='1234', character_id=1,
character_name='character.name', character_name='character.name1',
corporation_id='character.corp.id', corporation_id=2345,
corporation_name='character.corp.name', corporation_name='character.corp.name',
corporation_ticker='c.c.t', # max 5 chars corporation_ticker='c.c.t', # max 5 chars
alliance_id='character.alliance.id', alliance_id=None
)
EveCharacter.objects.create(
character_id=2,
character_name='character.name2',
corporation_id=9876,
corporation_name='character.corp.name',
corporation_ticker='c.c.t', # max 5 chars
alliance_id=3456,
alliance_name='character.alliance.name', alliance_name='character.alliance.name',
) )
EveCharacter.objects.create(
character_id=3,
character_name='character.name3',
corporation_id=9876,
corporation_name='character.corp.name',
corporation_ticker='c.c.t', # max 5 chars
alliance_id=3456,
alliance_name='character.alliance.name',
)
EveCharacter.objects.create(
character_id=4,
character_name='character.name4',
corporation_id=9876,
corporation_name='character.corp.name',
corporation_ticker='c.c.t', # max 5 chars
alliance_id=3456,
alliance_name='character.alliance.name',
)
"""
EveCharacter.objects.create(
character_id=5,
character_name='character.name5',
corporation_id=9876,
corporation_name='character.corp.name',
corporation_ticker='c.c.t', # max 5 chars
alliance_id=3456,
alliance_name='character.alliance.name',
)
"""
def setUp(self):
self.affiliations = [
{'character_id': 1, 'corporation_id': 5},
{'character_id': 2, 'corporation_id': 9876, 'alliance_id': 3456},
{'character_id': 3, 'corporation_id': 9876, 'alliance_id': 7456},
{'character_id': 4, 'corporation_id': 9876, 'alliance_id': 3456}
]
self.names = [
{'id': 1, 'name': 'character.name1'},
{'id': 2, 'name': 'character.name2'},
{'id': 3, 'name': 'character.name3'},
{'id': 4, 'name': 'character.name4_new'}
]
def test_normal_run(
self,
mock_provider,
mock_update_corp,
mock_update_alliance,
mock_update_character,
):
def get_affiliations(characters: list):
response = [x for x in self.affiliations if x['character_id'] in characters]
mock_operator = Mock(**{'result.return_value': response})
return mock_operator
def get_names(ids: list):
response = [x for x in self.names if x['id'] in ids]
mock_operator = Mock(**{'result.return_value': response})
return mock_operator
mock_provider.client.Character.post_characters_affiliation.side_effect \
= get_affiliations
mock_provider.client.Universe.post_universe_names.side_effect = get_names
run_model_update() run_model_update()
self.assertEqual(
mock_provider.client.Character.post_characters_affiliation.call_count, 2
)
self.assertEqual(
mock_provider.client.Universe.post_universe_names.call_count, 2
)
# character 1 has changed corp
# character 2 no change
# character 3 has changed alliance
# character 4 has changed name
self.assertEqual(mock_update_corp.apply_async.call_count, 1) self.assertEqual(mock_update_corp.apply_async.call_count, 1)
self.assertEqual( self.assertEqual(
int(mock_update_corp.apply_async.call_args[1]['args'][0]), 2345 int(mock_update_corp.apply_async.call_args[1]['args'][0]), 2345
) )
self.assertEqual(mock_update_alliance.apply_async.call_count, 1) self.assertEqual(mock_update_alliance.apply_async.call_count, 1)
self.assertEqual( self.assertEqual(
int(mock_update_alliance.apply_async.call_args[1]['args'][0]), 3456 int(mock_update_alliance.apply_async.call_args[1]['args'][0]), 3456
) )
characters_updated = {
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
}
excepted = {1, 3, 4}
self.assertSetEqual(characters_updated, excepted)
def test_ignore_character_not_in_affiliations(
self,
mock_provider,
mock_update_corp,
mock_update_alliance,
mock_update_character,
):
def get_affiliations(characters: list):
response = [x for x in self.affiliations if x['character_id'] in characters]
mock_operator = Mock(**{'result.return_value': response})
return mock_operator
def get_names(ids: list):
response = [x for x in self.names if x['id'] in ids]
mock_operator = Mock(**{'result.return_value': response})
return mock_operator
del self.affiliations[0]
mock_provider.client.Character.post_characters_affiliation.side_effect \
= get_affiliations
mock_provider.client.Universe.post_universe_names.side_effect = get_names
self.assertEqual(mock_update_character.apply_async.call_count, 1) run_model_update()
self.assertEqual( characters_updated = {
int(mock_update_character.apply_async.call_args[1]['args'][0]), 1234 x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
) }
excepted = {3, 4}
self.assertSetEqual(characters_updated, excepted)
def test_ignore_character_not_in_names(
self,
mock_provider,
mock_update_corp,
mock_update_alliance,
mock_update_character,
):
def get_affiliations(characters: list):
response = [x for x in self.affiliations if x['character_id'] in characters]
mock_operator = Mock(**{'result.return_value': response})
return mock_operator
def get_names(ids: list):
response = [x for x in self.names if x['id'] in ids]
mock_operator = Mock(**{'result.return_value': response})
return mock_operator
del self.names[3]
mock_provider.client.Character.post_characters_affiliation.side_effect \
= get_affiliations
mock_provider.client.Universe.post_universe_names.side_effect = get_names
run_model_update()
characters_updated = {
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
}
excepted = {1, 3}
self.assertSetEqual(characters_updated, excepted)

View File

@@ -6,7 +6,7 @@ from allianceauth.services.hooks import MenuItemHook, UrlHook
@hooks.register('menu_item_hook') @hooks.register('menu_item_hook')
def register_menu(): def register_menu():
return MenuItemHook(_('Fleet Activity Tracking'), 'fa fa-users fa-lightbulb-o fa-fw', 'fatlink:view', return MenuItemHook(_('Fleet Activity Tracking'), 'fas fa-users fa-fw', 'fatlink:view',
navactive=['fatlink:']) navactive=['fatlink:'])

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Create Fatlink" %}{% endblock page_title %} {% block page_title %}{% trans "Create Fatlink" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %} {% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Personal fatlink statistics" %}{% endblock page_title %} {% block page_title %}{% trans "Personal fatlink statistics" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Personal fatlink statistics" %}{% endblock page_title %} {% block page_title %}{% trans "Personal fatlink statistics" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Fatlink Corp Statistics" %}{% endblock page_title %} {% block page_title %}{% trans "Fatlink Corp Statistics" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Fatlink statistics" %}{% endblock page_title %} {% block page_title %}{% trans "Fatlink statistics" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %} {% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %}

View File

@@ -41,7 +41,7 @@ class AuthGroupInlineAdmin(admin.StackedInline):
kwargs["queryset"] = Group.objects.order_by(Lower('name')) kwargs["queryset"] = Group.objects.order_by(Lower('name'))
return super().formfield_for_manytomany(db_field, request, **kwargs) return super().formfield_for_manytomany(db_field, request, **kwargs)
def has_add_permission(self, request): def has_add_permission(self, request, obj=None):
return False return False
def has_delete_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None):

View File

@@ -0,0 +1,43 @@
from django.utils.translation import ugettext_lazy as _
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth import hooks
from . import urls
from .managers import GroupManager
class GroupManagementMenuItem(MenuItemHook):
""" This class ensures only authorized users will see the menu entry """
def __init__(self):
# setup menu entry for sidebar
MenuItemHook.__init__(
self,
text=_("Group Management"),
classes="fas fa-users-cog fa-fw",
url_name="groupmanagement:management",
order=50,
navactive=[
"groupmanagement:management", # group requests view
"groupmanagement:membership", # group membership view
"groupmanagement:audit_log", # group audit log view
],
)
def render(self, request):
if GroupManager.can_manage_groups(request.user):
app_count = GroupManager.pending_requests_count_for_user(request.user)
self.count = app_count if app_count and app_count > 0 else None
return MenuItemHook.render(self, request)
return ""
@hooks.register("menu_item_hook")
def register_menu():
return GroupManagementMenuItem()
@hooks.register("url_hook")
def register_urls():
return UrlHook(urls, "group", r"^groups/")

View File

@@ -1,5 +0,0 @@
from allianceauth.groupmanagement.managers import GroupManager
def can_manage_groups(request):
return {'can_manage_groups': GroupManager.can_manage_groups(request.user)}

View File

@@ -4,6 +4,7 @@ from django.contrib.auth.models import Group, User
from django.db.models import Q, QuerySet from django.db.models import Q, QuerySet
from allianceauth.authentication.models import State from allianceauth.authentication.models import State
from .models import GroupRequest
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -101,3 +102,18 @@ class GroupManager:
if user.is_authenticated: if user.is_authenticated:
return cls.has_management_permission(user) or cls.get_group_leaders_groups(user).filter(pk=group.pk).exists() return cls.has_management_permission(user) or cls.get_group_leaders_groups(user).filter(pk=group.pk).exists()
return False return False
@classmethod
def pending_requests_count_for_user(cls, user: User) -> int:
"""Returns the number of pending group requests for the given user"""
if cls.has_management_permission(user):
return GroupRequest.objects.filter(status="pending").count()
else:
return (
GroupRequest.objects
.filter(status="pending")
.filter(group__authgroup__group_leaders__exact=user)
.select_related("group__authgroup__group_leaders")
.count()
)

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.1.1 on 2020-09-18 14:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('groupmanagement', '0013_fix_requestlog_date_field'),
]
operations = [
migrations.AlterField(
model_name='requestlog',
name='request_type',
field=models.BooleanField(null=True),
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 3.1.2 on 2020-10-25 11:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("groupmanagement", "0014_auto_20200918_1412"),
]
operations = [
migrations.AlterField(
model_name="authgroup",
name="description",
field=models.TextField(
blank=True,
help_text="Short description <i>(max. 512 characters)</i> of the group shown to users.",
max_length=512,
),
),
]

View File

@@ -4,7 +4,6 @@ from django.db import models
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from allianceauth.authentication.models import State from allianceauth.authentication.models import State
from datetime import datetime
class GroupRequest(models.Model): class GroupRequest(models.Model):
@@ -26,7 +25,7 @@ class GroupRequest(models.Model):
class RequestLog(models.Model): class RequestLog(models.Model):
request_type = models.NullBooleanField(default=0) request_type = models.BooleanField(null=True)
group = models.ForeignKey(Group, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE)
request_info = models.CharField(max_length=254) request_info = models.CharField(max_length=254)
action = models.BooleanField(default=0) action = models.BooleanField(default=0)
@@ -108,7 +107,7 @@ class AuthGroup(models.Model):
help_text="States listed here will have the ability to join this group provided " help_text="States listed here will have the ability to join this group provided "
"they have the proper permissions.") "they have the proper permissions.")
description = models.CharField(max_length=512, blank=True, help_text="Description of the group shown to users.") description = models.TextField(max_length=512, blank=True, help_text="Short description <i>(max. 512 characters)</i> of the group shown to users.")
def __str__(self): def __str__(self):
return self.group.name return self.group.name

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %} {% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %}
@@ -8,65 +8,73 @@
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{{ group }} - {% trans 'Audit Log' %} {{ group }} - {% trans "Audit Log" %}
</div> </div>
<div class="panel-body">
<p> <div class="panel-body">
<p>
<a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button"> <a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button">
{% trans "Back" %} {% trans "Back" %}
</a> </a>
</p> </p>
{% if entries %} {% if entries %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped" id="log-entries"> <table class="table table-striped" id="log-entries">
<thead> <thead>
<th class="text-center" scope="col">{% trans "Date/Time" %}</th> <th scope="col">{% trans "Date/Time" %}</th>
<th class="text-center" scope="col">{% trans "Requestor" %}</th> <th scope="col">{% trans "Requestor" %}</th>
<th class="text-center" scope="col">{% trans "Character" %}</th> <th scope="col">{% trans "Character" %}</th>
<th class="text-center" scope="col">{% trans "Corporation" %}</th> <th scope="col">{% trans "Corporation" %}</th>
<th class="text-center" scope="col">{% trans "Type" %}</th> <th scope="col">{% trans "Type" %}</th>
<th class="text-center" scope="col">{% trans "Action" %}</th> <th scope="col">{% trans "Action" %}</th>
<th class="text-center" scope="col">{% trans "Actor" %}</th> <th scope="col">{% trans "Actor" %}</th>
</thead> </thead>
<tbody> <tbody>
{% for entry in entries %} {% for entry in entries %}
<tr> <tr>
<td class="text-center">{{ entry.date|date:"Y-M-d H:i" }}</td> <td>{{ entry.date|date:"Y-M-d, H:i" }}</td>
<td class="text-center">{{ entry.requestor }}</td> <td>{{ entry.requestor }}</td>
<td class="text-center">{{ entry.req_char }}</td> <td>{{ entry.req_char }}</td>
<td class="text-center">{{ entry.req_char.corporation_name }}</td> <td>{{ entry.req_char.corporation_name }}</td>
<td class="text-center">{{ entry.type_to_str }}</td> <td>{{ entry.type_to_str }}</td>
{% if entry.request_type is None %} {% if entry.request_type is None %}
<td class="text-center"> Removed</td> <td>{% trans "Removed" %}</td>
{% else %} {% else %}
<td class="text-center">{{ entry.action_to_str }}</td> <td>{{ entry.action_to_str }}</td>
{% endif %} {% endif %}
<td class="text-center">{{ entry.request_actor }}</td>
<td>{{ entry.request_actor }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<p class="text-muted"> <p class="text-muted">
All times displayed are EVE/UTC. {% trans "All times displayed are EVE/UTC." %}
</p> </p>
</div> </div>
{% else %} {% else %}
<div class="clearfix"></div> <div class="clearfix"></div>
<br> <br>
<div class="alert alert-warning text-center"> <div class="alert alert-warning text-center">
{% trans "No entries found for this group." %} {% trans "No entries found for this group." %}
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block extra_javascript %} {% block extra_javascript %}
{% include 'bundles/datatables-js.html' %} {% include 'bundles/datatables-js.html' %}
<script type="text/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script> {% include 'bundles/moment-js.html' with locale=True %}
<script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
{% endblock %} {% endblock %}
{% block extra_css %} {% block extra_css %}
@@ -74,12 +82,30 @@
{% endblock %} {% endblock %}
{% block extra_script %} {% block extra_script %}
$.fn.dataTable.moment = function(format, locale) {
var types = $.fn.dataTable.ext.type;
// Add type detection
types.detect.unshift(function(d) {
return moment(d, format, locale, true).isValid() ?
'moment-'+format :
null;
});
// Add sorting method - use an integer for the sorting
types.order[ 'moment-'+format+'-pre' ] = function(d) {
return moment(d, format, locale, true).unix();
};
};
$(document).ready(function(){ $(document).ready(function(){
$.fn.dataTable.moment('YYYY-MMM-D, HH:mm');
$('#log-entries').DataTable({ $('#log-entries').DataTable({
order: [[ 0, 'desc' ], [ 1, 'asc' ] ], order: [[0, 'desc'], [1, 'asc']],
filterDropDown: filterDropDown:
{ {
columns: [ columns: [
{ {
idx: 1 idx: 1
}, },
@@ -104,4 +130,3 @@
}); });
}); });
{% endblock %} {% endblock %}

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% load evelinks %} {% load evelinks %}
@@ -9,38 +9,35 @@
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{{ group.name }} - {% trans 'Members' %} {{ group.name }} - {% trans 'Members' %}
</div> </div>
<div class="panel-body">
<p> <div class="panel-body">
<p>
<a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button"> <a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button">
{% trans "Back" %} {% trans "Back" %}
</a> </a>
</p> </p>
{% if group.user_set %}
{% if group.user_set %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-aa" id="tab_group_members"> <table class="table table-aa" id="tab_group_members">
<thead> <thead>
<tr> <tr>
<th class="text-right">{% trans "Portrait" %}</th> <th>{% trans "Character" %}</th>
<th class="text-center">{% trans "Character" %}</th> <th>{% trans "Organization" %}</th>
<th class="text-center">{% trans "Organization" %}</th> <th></th>
<th class="text-center"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for member in members %} {% for member in members %}
<tr> <tr>
<td class="text-right"> <td>
{% if member.is_leader %} <img src="{{ member.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
<i class="fa fa-star"></i>&nbsp;
{% endif %}
<img src="{{ member.main_char|character_portrait_url:32 }}" class="img-circle">
</td>
<td class="text-center">
{% if member.main_char %} {% if member.main_char %}
<a href="{{ member.main_char|evewho_character_url }}" target="_blank"> <a href="{{ member.main_char|evewho_character_url }}" target="_blank">
{{ member.main_char.character_name }} {{ member.main_char.character_name }}
@@ -48,28 +45,36 @@
{% else %} {% else %}
{{ member.user.username }} {{ member.user.username }}
{% endif %} {% endif %}
{% if member.is_leader %}
<i class="fas fa-star" title="{% trans "Group leader" %}" style="margin-left: 1rem;"></i>&nbsp;
{% endif %}
</td> </td>
<td class="text-center">
<td>
{% if member.main_char %} {% if member.main_char %}
<a href="{{ member.main_char|dotlan_corporation_url }}" target="_blank"> <a href="{{ member.main_char|dotlan_corporation_url }}" target="_blank">
{{ member.main_char.corporation_name }} {{ member.main_char.corporation_name }}
</a><br> </a><br>
{{ member.main_char.alliance_name|default_if_none:"" }} {{ member.main_char.alliance_name|default_if_none:"" }}
{% else %} {% else %}
(unknown) {% trans "(unknown)" %}
{% endif %} {% endif %}
</td> </td>
<td class="text-center">
<a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger" <td class="text-right">
title="{% trans "Remove from group" %}"> <a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger" title="{% trans "Remove from group" %}">
<i class="glyphicon glyphicon-remove"></i> <i class="glyphicon glyphicon-remove"></i>
</a> </a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<p class="text-muted"><i class="fa fa-star"></i>: Group leader</p>
<p class="text-muted">
<i class="fas fa-star"></i>: {% trans "Group leader" %}
</p>
</div> </div>
{% else %} {% else %}
<div class="alert alert-warning text-center"> <div class="alert alert-warning text-center">
@@ -77,7 +82,7 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}
@@ -93,10 +98,13 @@
{% block extra_script %} {% block extra_script %}
$(document).ready(function(){ $(document).ready(function(){
$('#tab_group_members').DataTable({ $('#tab_group_members').DataTable({
order: [ [ 1, "asc" ] ], order: [[0, "asc"]],
columnDefs: [ columnDefs: [
{ "sortable": false, "targets": [0, 3] }, {
"sortable": false,
"targets": [2]
},
] ]
}); });
}); });
{% endblock %} {% endblock %}

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Groups Membership" %}{% endblock page_title %} {% block page_title %}{% trans "Groups Membership" %}{% endblock page_title %}
@@ -9,31 +9,36 @@
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{% trans "Groups" %} {% trans "Groups" %}
</div> </div>
<div class="panel-body"> <div class="panel-body">
{% if groups %} {% if groups %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-aa"> <table class="table table-aa">
<thead> <thead>
<tr> <tr>
<th class="text-center">{% trans "Name" %}</th> <th>{% trans "Name" %}</th>
<th class="text-center">{% trans "Description" %}</th> <th>{% trans "Description" %}</th>
<th class="text-center">{% trans "Status" %}</th> <th>{% trans "Status" %}</th>
<th class="text-center">{% trans "Member Count" %}</th> <th style="white-space: nowrap;">{% trans "Member Count" %}</th>
<th class="text-center"></th> <th style="min-width: 170px;"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for group in groups %} {% for group in groups %}
<tr> <tr>
<td class="text-center"> <td>
<a href="{% url 'groupmanagement:membership_list' group.id %}">{{ group.name }}</a> <a href="{% url 'groupmanagement:membership' group.id %}">{{ group.name }}</a>
</td> </td>
<td class="text-center">{{ group.authgroup.description }}</td>
<td class="text-center"> <td>{{ group.authgroup.description|linebreaks|urlize }}</td>
<td>
{% if group.authgroup.hidden %} {% if group.authgroup.hidden %}
<span class="label label-info">{% trans "Hidden" %}</span> <span class="label label-info">{% trans "Hidden" %}</span>
{% elif group.authgroup.open %} {% elif group.authgroup.open %}
@@ -42,21 +47,23 @@
<span class="label label-default">{% trans "Requestable" %}</span> <span class="label label-default">{% trans "Requestable" %}</span>
{% endif %} {% endif %}
</td> </td>
<td class="text-center">
<td class="text-right">
{{ group.num_members }} {{ group.num_members }}
</td> </td>
<td class="text-center">
<a href="{% url 'groupmanagement:membership_list' group.id %}" class="btn btn-primary" <td class="text-right">
title="{% trans "View Members" %}"> <a href="{% url 'groupmanagement:membership' group.id %}" class="btn btn-primary" title="{% trans "View Members" %}">
<i class="glyphicon glyphicon-eye-open"></i> <i class="glyphicon glyphicon-eye-open"></i>
</a> </a>
<a href="{% url "groupmanagement:audit_log" group.id %}" class="btn btn-info" title="{% trans "Audit Members" %}"> <a href="{% url "groupmanagement:audit_log" group.id %}" class="btn btn-info" title="{% trans "Audit Members" %}">
<i class="glyphicon glyphicon-list-alt"></i> <i class="glyphicon glyphicon-list-alt"></i>
</a> </a>
<a id="clipboard-copy" data-clipboard-text="{{ request.scheme }}://{{request.get_host}}{% url 'groupmanagement:request_add' group.id %}" class="btn btn-warning" title="{% trans "Copy Direct Join Link" %}"> <a id="clipboard-copy" data-clipboard-text="{{ request.scheme }}://{{request.get_host}}{% url 'groupmanagement:request_add' group.id %}" class="btn btn-warning" title="{% trans "Copy Direct Join Link" %}">
<i class="glyphicon glyphicon-copy"></i> <i class="glyphicon glyphicon-copy"></i>
</a> </a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@@ -72,9 +79,11 @@
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}
{% block extra_javascript %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script> {% block extra_javascript %}
<script> {% include 'bundles/clipboard-js.html' %}
new ClipboardJS('#clipboard-copy');
</script> <script>
{% endblock %} new ClipboardJS('#clipboard-copy');
</script>
{% endblock %}

View File

@@ -1,10 +1,10 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Available Groups" %}{% endblock page_title %} {% block page_title %}{% trans "Available Groups" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %} {% block extra_css %}{% endblock extra_css %}
url
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
<h1 class="page-header text-center">{% trans "Available Groups" %}</h1> <h1 class="page-header text-center">{% trans "Available Groups" %}</h1>
@@ -12,17 +12,18 @@ url
<table class="table table-aa"> <table class="table table-aa">
<thead> <thead>
<tr> <tr>
<th class="text-center">{% trans "Name" %}</th> <th>{% trans "Name" %}</th>
<th class="text-center">{% trans "Description" %}</th> <th>{% trans "Description" %}</th>
<th class="text-center">{% trans "Action" %}</th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for g in groups %} {% for g in groups %}
<tr> <tr>
<td class="text-center">{{ g.group.name }}</td> <td>{{ g.group.name }}</td>
<td class="text-center">{{ g.group.authgroup.description|urlize }}</td> <td>{{ g.group.authgroup.description|linebreaks|urlize }}</td>
<td class="text-center"> <td class="text-right">
{% if g.group in user.groups.all %} {% if g.group in user.groups.all %}
{% if not g.request %} {% if not g.request %}
<a href="{% url 'groupmanagement:request_leave' g.group.id %}" class="btn btn-danger"> <a href="{% url 'groupmanagement:request_leave' g.group.id %}" class="btn btn-danger">
@@ -59,5 +60,4 @@ url
</div> </div>
{% endif %} {% endif %}
</div> </div>
{% endblock content %} {% endblock content %}

View File

@@ -1,28 +1,29 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% load evelinks %} {% load evelinks %}
{% block page_title %}{% trans "Groups Management" %}{% endblock page_title %} {% block page_title %}{% trans "Groups Management" %}{% endblock page_title %}
{% block extra_css %}
<style>
.nav-tabs>li.active>a {
background-color: #ECF0F1 !important;
color: #2C3E50;
}
</style>
{% block extra_css %}
<style>
.nav-tabs > li.active > a {
background-color: rgb(236, 240, 241) !important;
color: rgb(44, 62, 80);
}
</style>
{% endblock extra_css %} {% endblock extra_css %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"> <li class="active">
<a data-toggle="tab" href="#add"> <a data-toggle="tab" href="#add">
{% trans "Join Requests" %} {% trans "Join Requests" %}
{% if acceptrequests %} {% if acceptrequests %}
<span class="badge">{{ acceptrequests|length }}</span> <span class="badge">{{ acceptrequests|length }}</span>
{% endif %} {% endif %}
@@ -31,133 +32,130 @@
<li> <li>
<a data-toggle="tab" href="#leave"> <a data-toggle="tab" href="#leave">
{% trans "Leave Requests" %} {% trans "Leave Requests" %}
{% if leaverequests %} {% if leaverequests %}
<span class="badge">{{ leaverequests|length }}</span> <span class="badge">{{ leaverequests|length }}</span>
{% endif %} {% endif %}
</a> </a>
</li> </li>
</ul> </ul>
<div class="tab-content">
<div class="tab-content">
<div id="add" class="tab-pane fade in active panel panel-default"> <div id="add" class="tab-pane fade in active panel panel-default">
<div class="panel-body"> <div class="panel-body">
{% if acceptrequests %} {% if acceptrequests %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-aa"> <table class="table table-aa">
<thead> <thead>
<tr> <tr>
<th class="text-center"></th> <th>{% trans "Character" %}</th>
<th class="text-center">{% trans "Character" %}</th> <th>{% trans "Organization" %}</th>
<th class="text-center">{% trans "Organization" %}</th> <th>{% trans "Group" %}</th>
<th class="text-center">{% trans "Group" %}</th> <th></th>
<th class="text-center"></th>
</tr>
</thead>
<tbody>
{% for acceptrequest in acceptrequests %}
<tr>
<td class="text-right">
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle">
</td>
<td class="text-center">
{% if acceptrequest.main_char %}
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
{{ acceptrequest.main_char.character_name }}
</a>
{% else %}
{{ acceptrequest.user.username }}
{% endif %}
</td>
<td class="text-center">
{% if acceptrequest.main_char %}
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
{{ acceptrequest.main_char.corporation_name }}
</a><br>
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
{% else %}
(unknown)
{% endif %}
</td>
<td class="text-center">{{ acceptrequest.group.name }}</td>
<td class="text-center">
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
{% trans "Accept" %}
</a>
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
{% trans "Reject" %}
</a>
</td>
</tr> </tr>
{% endfor %} </thead>
</tbody>
</table> <tbody>
</div> {% for acceptrequest in acceptrequests %}
{% else %} <tr>
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div> <td>
{% endif %} <img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
{% if acceptrequest.main_char %}
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
{{ acceptrequest.main_char.character_name }}
</a>
{% else %}
{{ acceptrequest.user.username }}
{% endif %}
</td>
<td>
{% if acceptrequest.main_char %}
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
{{ acceptrequest.main_char.corporation_name }}
</a><br>
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
{% else %}
{% trans "(unknown)" %}
{% endif %}
</td>
<td>{{ acceptrequest.group.name }}</td>
<td class="text-right">
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
{% trans "Accept" %}
</a>
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
{% trans "Reject" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
{% endif %}
</div> </div>
</div> </div>
<div id="leave" class="tab-pane fade panel panel-default"> <div id="leave" class="tab-pane fade panel panel-default">
<div class="panel-body"> <div class="panel-body">
{% if leaverequests %} {% if leaverequests %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-aa"> <table class="table table-aa">
<thead> <thead>
<tr> <tr>
<th class="text-center"></th> <th>{% trans "Character" %}</th>
<th class="text-center">{% trans "Character" %}</th> <th>{% trans "Organization" %}</th>
<th class="text-center">{% trans "Organization" %}</th> <th>{% trans "Group" %}</th>
<th class="text-center">{% trans "Group" %}</th> <th></th>
<th class="text-center"></th>
</tr>
</thead>
<tbody>
{% for leaverequest in leaverequests %}
<tr>
<td class="text-right">
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle">
</td>
<td class="text-center">
{% if leaverequest.main_char %}
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
{{ leaverequest.main_char.character_name }}
</a>
{% else %}
{{ leaverequest.user.username }}
{% endif %}
</td>
<td class="text-center">
{% if leaverequest.main_char %}
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
{{ leaverequest.main_char.corporation_name }}
</a><br>
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
{% else %}
(unknown)
{% endif %}
</td>
<td class="text-center">{{ leaverequest.group.name }}</td>
<td class="text-center">
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
{% trans "Accept" %}
</a>
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
{% trans "Reject" %}
</a>
</td>
</tr> </tr>
{% endfor %} </thead>
</tbody>
</table> <tbody>
</div> {% for leaverequest in leaverequests %}
{% else %} <tr>
<div class="alert alert-warning text-center">{% trans "No group leave requests." %}</div> <td>
{% endif %} <img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
{% if leaverequest.main_char %}
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
{{ leaverequest.main_char.character_name }}
</a>
{% else %}
{{ leaverequest.user.username }}
{% endif %}
</td>
<td>
{% if leaverequest.main_char %}
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
{{ leaverequest.main_char.corporation_name }}
</a><br>
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
{% else %}
{% trans "(unknown)" %}
{% endif %}
</td>
<td>{{ leaverequest.group.name }}</td>
<td class="text-right">
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
{% trans "Accept" %}
</a>
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
{% trans "Reject" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-warning text-center">{% trans "No group leave requests." %}</div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@@ -1,10 +1,9 @@
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% load navactive %} {% load navactive %}
<nav class="navbar navbar-default"> <nav class="navbar navbar-default">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">{% trans "Toggle navigation" %}</span> <span class="sr-only">{% trans "Toggle navigation" %}</span>
@@ -12,7 +11,7 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" href="">{% trans "Group Management" %}</a> <a class="navbar-brand" href="{% url 'groupmanagement:management' %}">{% trans "Group Management" %}</a>
</div> </div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
@@ -20,11 +19,10 @@
<li class="{% navactive request 'groupmanagement:management' %}"> <li class="{% navactive request 'groupmanagement:management' %}">
<a href="{% url 'groupmanagement:management' %}">{% trans "Group Requests" %}</a> <a href="{% url 'groupmanagement:management' %}">{% trans "Group Requests" %}</a>
</li> </li>
<li class="{% renavactive request '^/group/membership/' %}"> <li class="{% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}">
<a href="{% url 'groupmanagement:membership' %}">{% trans "Group Membership" %}</a> <a href="{% url 'groupmanagement:membership' %}">{% trans "Group Membership" %}</a>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>

View File

@@ -11,11 +11,7 @@ from allianceauth.eveonline.models import (
EveCharacter, EveCorporationInfo, EveAllianceInfo EveCharacter, EveCorporationInfo, EveAllianceInfo
) )
from ..admin import ( from ..admin import HasLeaderFilter, GroupAdmin, Group
HasLeaderFilter,
GroupAdmin,
Group
)
from . import get_admin_change_view_url from . import get_admin_change_view_url
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS: if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
@@ -88,33 +84,33 @@ class TestGroupAdmin(TestCase):
# user 1 - corp and alliance, normal user # user 1 - corp and alliance, normal user
cls.character_1 = EveCharacter.objects.create( cls.character_1 = EveCharacter.objects.create(
character_id='1001', character_id=1001,
character_name='Bruce Wayne', character_name='Bruce Wayne',
corporation_id='2001', corporation_id=2001,
corporation_name='Wayne Technologies', corporation_name='Wayne Technologies',
corporation_ticker='WT', corporation_ticker='WT',
alliance_id='3001', alliance_id=3001,
alliance_name='Wayne Enterprises', alliance_name='Wayne Enterprises',
alliance_ticker='WE', alliance_ticker='WE',
) )
cls.character_1a = EveCharacter.objects.create( cls.character_1a = EveCharacter.objects.create(
character_id='1002', character_id=1002,
character_name='Batman', character_name='Batman',
corporation_id='2001', corporation_id=2001,
corporation_name='Wayne Technologies', corporation_name='Wayne Technologies',
corporation_ticker='WT', corporation_ticker='WT',
alliance_id='3001', alliance_id=3001,
alliance_name='Wayne Enterprises', alliance_name='Wayne Enterprises',
alliance_ticker='WE', alliance_ticker='WE',
) )
alliance = EveAllianceInfo.objects.create( alliance = EveAllianceInfo.objects.create(
alliance_id='3001', alliance_id=3001,
alliance_name='Wayne Enterprises', alliance_name='Wayne Enterprises',
alliance_ticker='WE', alliance_ticker='WE',
executor_corp_id='2001' executor_corp_id=2001
) )
EveCorporationInfo.objects.create( EveCorporationInfo.objects.create(
corporation_id='2001', corporation_id=2001,
corporation_name='Wayne Technologies', corporation_name='Wayne Technologies',
corporation_ticker='WT', corporation_ticker='WT',
member_count=42, member_count=42,
@@ -189,10 +185,10 @@ class TestGroupAdmin(TestCase):
alliance=None alliance=None
) )
EveAllianceInfo.objects.create( EveAllianceInfo.objects.create(
alliance_id='3101', alliance_id=3101,
alliance_name='Lex World Domination', alliance_name='Lex World Domination',
alliance_ticker='LWD', alliance_ticker='LWD',
executor_corp_id='' executor_corp_id=2101
) )
cls.user_3 = User.objects.create_user( cls.user_3 = User.objects.create_user(
cls.character_3.character_name.replace(' ', '_'), cls.character_3.character_name.replace(' ', '_'),
@@ -219,8 +215,8 @@ class TestGroupAdmin(TestCase):
"""create autogroups for corps and alliances""" """create autogroups for corps and alliances"""
if _has_auto_groups: if _has_auto_groups:
autogroups_config = AutogroupsConfig( autogroups_config = AutogroupsConfig(
corp_groups = True, corp_groups=True,
alliance_groups = True alliance_groups=True
) )
autogroups_config.save() autogroups_config.save()
for state in State.objects.all(): for state in State.objects.all():
@@ -277,7 +273,7 @@ class TestGroupAdmin(TestCase):
if _has_auto_groups: if _has_auto_groups:
@patch(MODULE_PATH + '._has_auto_groups', True) @patch(MODULE_PATH + '._has_auto_groups', True)
def test_properties_6(self): def test_properties_7(self):
self._create_autogroups() self._create_autogroups()
expected = ['Auto Group'] expected = ['Auto Group']
my_group = Group.objects\ my_group = Group.objects\
@@ -337,8 +333,8 @@ class TestGroupAdmin(TestCase):
changelist = my_modeladmin.get_changelist_instance(request) changelist = my_modeladmin.get_changelist_instance(request)
queryset = changelist.get_queryset(request) queryset = changelist.get_queryset(request)
expected = Group.objects.exclude( expected = Group.objects.exclude(
managedalliancegroup__isnull=True, managedalliancegroup__isnull=True,
managedcorpgroup__isnull=True managedcorpgroup__isnull=True
) )
self.assertSetEqual(set(queryset), set(expected)) self.assertSetEqual(set(queryset), set(expected))
@@ -394,4 +390,4 @@ class TestGroupAdmin(TestCase):
c = Client() c = Client()
c.login(username='superuser', password='secret') c.login(username='superuser', password='secret')
response = c.get(get_admin_change_view_url(self.group_1)) response = c.get(get_admin_change_view_url(self.group_1))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View File

@@ -7,7 +7,7 @@ from django.urls import reverse
from allianceauth.eveonline.models import EveCorporationInfo, EveAllianceInfo from allianceauth.eveonline.models import EveCorporationInfo, EveAllianceInfo
from allianceauth.tests.auth_utils import AuthUtils from allianceauth.tests.auth_utils import AuthUtils
from ..models import AuthGroup from ..models import GroupRequest
from ..managers import GroupManager from ..managers import GroupManager
@@ -15,6 +15,7 @@ class MockUserNotAuthenticated():
def __init__(self): def __init__(self):
self.is_authenticated = False self.is_authenticated = False
class GroupManagementVisibilityTestCase(TestCase): class GroupManagementVisibilityTestCase(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@@ -37,22 +38,20 @@ class GroupManagementVisibilityTestCase(TestCase):
def _refresh_user(self): def _refresh_user(self):
self.user = User.objects.get(pk=self.user.pk) self.user = User.objects.get(pk=self.user.pk)
def test_get_group_leaders_groups(self): def test_get_group_leaders_groups(self):
self.group1.authgroup.group_leaders.add(self.user) self.group1.authgroup.group_leaders.add(self.user)
self.group2.authgroup.group_leader_groups.add(self.group1) self.group2.authgroup.group_leader_groups.add(self.group1)
self._refresh_user() self._refresh_user()
groups = GroupManager.get_group_leaders_groups(self.user) groups = GroupManager.get_group_leaders_groups(self.user)
self.assertIn(self.group1, groups) #avail due to user self.assertIn(self.group1, groups) #avail due to user
self.assertNotIn(self.group2, groups) #not avail due to group self.assertNotIn(self.group2, groups) #not avail due to group
self.assertNotIn(self.group3, groups) #not avail at all self.assertNotIn(self.group3, groups) #not avail at all
self.user.groups.add(self.group1) self.user.groups.add(self.group1)
self._refresh_user() self._refresh_user()
groups = GroupManager.get_group_leaders_groups(self.user) groups = GroupManager.get_group_leaders_groups(self.user)
def test_can_manage_group(self): def test_can_manage_group(self):
self.group1.authgroup.group_leaders.add(self.user) self.group1.authgroup.group_leaders.add(self.user)
self.user.groups.add(self.group1) self.user.groups.add(self.group1)
@@ -182,7 +181,6 @@ class TestGroupManager(TestCase):
]: ]:
self.assertFalse(GroupManager.joinable_group(x, member_state)) self.assertFalse(GroupManager.joinable_group(x, member_state))
def test_joinable_group_guest(self): def test_joinable_group_guest(self):
guest_state = AuthUtils.get_guest_state() guest_state = AuthUtils.get_guest_state()
for x in [ for x in [
@@ -200,7 +198,6 @@ class TestGroupManager(TestCase):
]: ]:
self.assertFalse(GroupManager.joinable_group(x, guest_state)) self.assertFalse(GroupManager.joinable_group(x, guest_state))
def test_get_all_non_internal_groups(self): def test_get_all_non_internal_groups(self):
result = GroupManager.get_all_non_internal_groups() result = GroupManager.get_all_non_internal_groups()
expected = { expected = {
@@ -224,7 +221,7 @@ class TestGroupManager(TestCase):
def test_get_joinable_groups_for_user_no_permission(self): def test_get_joinable_groups_for_user_no_permission(self):
AuthUtils.assign_state(self.user, AuthUtils.get_guest_state()) AuthUtils.assign_state(self.user, AuthUtils.get_guest_state())
result = GroupManager.get_joinable_groups_for_user(self.user) result = GroupManager.get_joinable_groups_for_user(self.user)
expected= {self.group_public_1, self.group_public_2} expected = {self.group_public_1, self.group_public_2}
self.assertSetEqual(set(result), expected) self.assertSetEqual(set(result), expected)
def test_get_joinable_groups_for_user_guest_w_permission_(self): def test_get_joinable_groups_for_user_guest_w_permission_(self):
@@ -335,3 +332,96 @@ class TestGroupManager(TestCase):
self.assertFalse( self.assertFalse(
GroupManager.can_manage_group(user, self.group_default) GroupManager.can_manage_group(user, self.group_default)
) )
class TestPendingRequestsCountForUser(TestCase):
def setUp(self) -> None:
self.group_1 = Group.objects.create(name="Group 1")
self.group_2 = Group.objects.create(name="Group 2")
self.user_leader_1 = AuthUtils.create_member('Clark Kent')
self.group_1.authgroup.group_leaders.add(self.user_leader_1)
self.user_leader_2 = AuthUtils.create_member('Peter Parker')
self.group_2.authgroup.group_leaders.add(self.user_leader_2)
self.user_requestor = AuthUtils.create_member('Bruce Wayne')
def test_single_request_for_leader(self):
# given user_leader_1 is leader of group_1
# and user_leader_2 is leader of group_2
# when user_requestor is requesting access to group 1
# then return 1 for user_leader 1 and 0 for user_leader_2
GroupRequest.objects.create(
status="pending", user=self.user_requestor, group=self.group_1
)
self.assertEqual(
GroupManager.pending_requests_count_for_user(self.user_leader_1), 1
)
self.assertEqual(
GroupManager.pending_requests_count_for_user(self.user_leader_2), 0
)
def test_return_none_for_none_leader(self):
# given user_requestor is leader of no group
# when user_requestor is requesting access to group 1
# then return 0 for user_requestor
GroupRequest.objects.create(
status="pending", user=self.user_requestor, group=self.group_1
)
self.assertEqual(
GroupManager.pending_requests_count_for_user(self.user_requestor), 0
)
def test_single_leave_request(self):
# given user_leader_2 is leader of group_2
# and user_requestor is member of group 2
# when user_requestor is requesting to leave group 2
# then return 1 for user_leader_2
self.user_requestor.groups.add(self.group_2)
GroupRequest.objects.create(
status="pending",
user=self.user_requestor,
group=self.group_2,
leave_request=True
)
self.assertEqual(
GroupManager.pending_requests_count_for_user(self.user_leader_2), 1
)
def test_join_and_leave_request(self):
# given user_leader_2 is leader of group_2
# and user_requestor is member of group 2
# when user_requestor is requesting to leave group 2
# and user_requestor_2 is requesting to join group 2
# then return 2 for user_leader_2
self.user_requestor.groups.add(self.group_2)
user_requestor_2 = AuthUtils.create_member("Lex Luther")
GroupRequest.objects.create(
status="pending",
user=user_requestor_2,
group=self.group_2
)
GroupRequest.objects.create(
status="pending",
user=self.user_requestor,
group=self.group_2,
leave_request=True
)
self.assertEqual(
GroupManager.pending_requests_count_for_user(self.user_leader_2), 2
)
def test_single_request_for_user_with_management_perm(self):
# given user_leader_4 which is leafer of no group
# but has the management permissions
# when user_requestor is requesting access to group 1
# then return 1 for user_leader_4
user_leader_4 = AuthUtils.create_member("Lex Luther")
AuthUtils.add_permission_to_user_by_name("auth.group_management", user_leader_4)
user_leader_4 = User.objects.get(pk=user_leader_4.pk)
GroupRequest.objects.create(
status="pending", user=self.user_requestor, group=self.group_1
)
self.assertEqual(
GroupManager.pending_requests_count_for_user(self.user_leader_1), 1
)

View File

@@ -1,32 +1,52 @@
from . import views from . import views
from django.conf.urls import include, url from django.conf.urls import url
app_name = 'groupmanagement'
app_name = "groupmanagement"
urlpatterns = [ urlpatterns = [
url(r'^groups/', views.groups_view, name='groups'), # groups
url(r'^group/', include([ url(r"^groups/$", views.groups_view, name="groups"),
url(r'^management/', views.group_management, url(r"^group/request/join/(\w+)/$", views.group_request_add, name="request_add"),
name='management'), url(
url(r'^membership/$', views.group_membership, r"^group/request/leave/(\w+)/$", views.group_request_leave, name="request_leave"
name='membership'), ),
url(r'^membership/(\w+)/$', views.group_membership_list, # group management
name='membership_list'), url(r"^groupmanagement/requests/$", views.group_management, name="management"),
url(r'^membership/(\w+)/audit/$', views.group_membership_audit, name="audit_log"), url(r"^groupmanagement/membership/$", views.group_membership, name="membership"),
url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove, url(
name='membership_remove'), r"^groupmanagement/membership/(\w+)/$",
url(r'^request_add/(\w+)', views.group_request_add, views.group_membership_list,
name='request_add'), name="membership",
url(r'^request/accept/(\w+)', views.group_accept_request, ),
name='accept_request'), url(
url(r'^request/reject/(\w+)', views.group_reject_request, r"^groupmanagement/membership/(\w+)/audit-log/$",
name='reject_request'), views.group_membership_audit,
name="audit_log",
url(r'^request_leave/(\w+)', views.group_request_leave, ),
name='request_leave'), url(
url(r'leave_request/accept/(\w+)', views.group_leave_accept_request, r"^groupmanagement/membership/(\w+)/remove/(\w+)/$",
name='leave_accept_request'), views.group_membership_remove,
url(r'^leave_request/reject/(\w+)', views.group_leave_reject_request, name="membership_remove",
name='leave_reject_request'), ),
])), url(
r"^groupmanagement/request/join/accept/(\w+)/$",
views.group_accept_request,
name="accept_request",
),
url(
r"^groupmanagement/request/join/reject/(\w+)/$",
views.group_reject_request,
name="reject_request",
),
url(
r"^groupmanagement/request/leave/accept/(\w+)/$",
views.group_leave_accept_request,
name="leave_accept_request",
),
url(
r"^groupmanagement/request/leave/reject/(\w+)/$",
views.group_leave_reject_request,
name="leave_reject_request",
),
] ]

View File

@@ -103,7 +103,7 @@ def group_membership_list(request, group_id):
# Check its a joinable group i.e. not corp or internal # Check its a joinable group i.e. not corp or internal
# And the user has permission to manage it # And the user has permission to manage it
if (not GroupManager.check_internal_group(group) if (not GroupManager.check_internal_group(group)
or not GroupManager.can_manage_group(request.user, group) or not GroupManager.can_manage_group(request.user, group)
): ):
logger.warning( logger.warning(
@@ -132,7 +132,7 @@ def group_membership_list(request, group_id):
render_items = {'group': group, 'members': members} render_items = {'group': group, 'members': members}
return render( return render(
request, 'groupmanagement/groupmembers.html', request, 'groupmanagement/groupmembers.html',
context=render_items context=render_items
) )
@@ -166,7 +166,7 @@ def group_membership_remove(request, group_id, user_id):
except ObjectDoesNotExist: except ObjectDoesNotExist:
messages.warning(request, _("Group does not exist")) messages.warning(request, _("Group does not exist"))
return redirect('groupmanagement:membership_list', group_id) return redirect('groupmanagement:membership', group_id)
@login_required @login_required
@@ -312,18 +312,18 @@ def group_leave_reject_request(request, group_request_id):
@login_required @login_required
def groups_view(request): def groups_view(request):
logger.debug("groups_view called by user %s" % request.user) logger.debug("groups_view called by user %s" % request.user)
groups_qs = GroupManager.get_joinable_groups_for_user( groups_qs = GroupManager.get_joinable_groups_for_user(
request.user, include_hidden=False request.user, include_hidden=False
) )
groups_qs = groups_qs.order_by('name') groups_qs = groups_qs.order_by('name')
groups = [] groups = []
for group in groups_qs: for group in groups_qs:
group_request = GroupRequest.objects\ group_request = GroupRequest.objects\
.filter(user=request.user)\ .filter(user=request.user)\
.filter(group=group) .filter(group=group)
groups.append({ groups.append({
'group': group, 'group': group,
'request': group_request[0] if group_request else None 'request': group_request[0] if group_request else None
}) })

View File

@@ -1,17 +1,25 @@
from allianceauth.services.hooks import MenuItemHook, UrlHook
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from allianceauth import hooks from allianceauth import hooks
from allianceauth.hrapplications import urls from allianceauth.services.hooks import MenuItemHook, UrlHook
from . import urls
from .models import Application
class ApplicationsMenu(MenuItemHook): class ApplicationsMenu(MenuItemHook):
def __init__(self): def __init__(self):
MenuItemHook.__init__(self, MenuItemHook.__init__(self,
_('Applications'), _('Applications'),
'fa fa-file-o fa-fw', 'far fa-file fa-fw',
'hrapplications:index', 'hrapplications:index',
navactive=['hrapplications:']) navactive=['hrapplications:'])
def render(self, request):
app_count = Application.objects.pending_requests_count_for_user(request.user)
self.count = app_count if app_count and app_count > 0 else None
return MenuItemHook.render(self, request)
@hooks.register('menu_item_hook') @hooks.register('menu_item_hook')
def register_menu(): def register_menu():

View File

@@ -0,0 +1,25 @@
from django.contrib.auth.models import User
from django.db import models
from typing import Optional
class ApplicationManager(models.Manager):
def pending_requests_count_for_user(self, user: User) -> Optional[int]:
"""Returns the number of pending group requests for the given user"""
if user.is_superuser:
return self.filter(approved__isnull=True).count()
elif user.has_perm("auth.human_resources"):
main_character = user.profile.main_character
if main_character:
return (
self
.select_related("form__corp")
.filter(form__corp__corporation_id=main_character.corporation_id)
.filter(approved__isnull=True)
.count()
)
else:
return None
else:
return None

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.1.1 on 2020-09-18 14:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hrapplications', '0006_remove_legacy_models'),
]
operations = [
migrations.AlterField(
model_name='application',
name='approved',
field=models.BooleanField(blank=True, default=None, null=True),
),
]

View File

@@ -2,8 +2,9 @@ from django.contrib.auth.models import User
from django.db import models from django.db import models
from sortedm2m.fields import SortedManyToManyField from sortedm2m.fields import SortedManyToManyField
from allianceauth.eveonline.models import EveCharacter from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo
from allianceauth.eveonline.models import EveCorporationInfo
from .managers import ApplicationManager
class ApplicationQuestion(models.Model): class ApplicationQuestion(models.Model):
@@ -22,6 +23,7 @@ class ApplicationChoice(models.Model):
def __str__(self): def __str__(self):
return self.choice_text return self.choice_text
class ApplicationForm(models.Model): class ApplicationForm(models.Model):
questions = SortedManyToManyField(ApplicationQuestion) questions = SortedManyToManyField(ApplicationQuestion)
corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE) corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE)
@@ -33,11 +35,13 @@ class ApplicationForm(models.Model):
class Application(models.Model): class Application(models.Model):
form = models.ForeignKey(ApplicationForm, on_delete=models.CASCADE, related_name='applications') form = models.ForeignKey(ApplicationForm, on_delete=models.CASCADE, related_name='applications')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications') user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications')
approved = models.NullBooleanField(blank=True, null=True, default=None) approved = models.BooleanField(blank=True, null=True, default=None)
reviewer = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True) reviewer = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
reviewer_character = models.ForeignKey(EveCharacter, on_delete=models.SET_NULL, blank=True, null=True) reviewer_character = models.ForeignKey(EveCharacter, on_delete=models.SET_NULL, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
objects = ApplicationManager()
def __str__(self): def __str__(self):
return str(self.user) + " Application To " + str(self.form) return str(self.user) + " Application To " + str(self.form)

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Choose a Corp" %}{% endblock page_title %} {% block page_title %}{% trans "Choose a Corp" %}{% endblock page_title %}

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Apply To" %} {{ corp.corporation_name }}{% endblock page_title %} {% block page_title %}{% trans "Apply To" %} {{ corp.corporation_name }}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "HR Application Management" %}{% endblock page_title %} {% block page_title %}{% trans "HR Application Management" %}{% endblock page_title %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}HR Application Management{% endblock page_title %} {% block page_title %}HR Application Management{% endblock page_title %}

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load bootstrap %} {% load bootstrap %}
{% load i18n %} {% load i18n %}

View File

@@ -1 +1,103 @@
# Create your tests here. from django.contrib.auth.models import User
from django.test import TestCase
from allianceauth.eveonline.models import EveCorporationInfo
from allianceauth.tests.auth_utils import AuthUtils
from .models import Application, ApplicationForm, ApplicationQuestion, ApplicationChoice
class TestApplicationManagersPendingRequestsCountForUser(TestCase):
def setUp(self) -> None:
self.corporation_1 = EveCorporationInfo.objects.create(
corporation_id=2001, corporation_name="Wayne Tech", member_count=42
)
self.corporation_2 = EveCorporationInfo.objects.create(
corporation_id=2011, corporation_name="Lex Corp", member_count=666
)
question = ApplicationQuestion.objects.create(title="Dummy Question")
ApplicationChoice.objects.create(question=question, choice_text="yes")
ApplicationChoice.objects.create(question=question, choice_text="no")
self.form_corporation_1 = ApplicationForm.objects.create(
corp=self.corporation_1
)
self.form_corporation_1.questions.add(question)
self.form_corporation_2 = ApplicationForm.objects.create(
corp=self.corporation_2
)
self.form_corporation_2.questions.add(question)
self.user_requestor = AuthUtils.create_member("Peter Parker")
self.user_manager = AuthUtils.create_member("Bruce Wayne")
AuthUtils.add_main_character_2(
self.user_manager,
self.user_manager.username,
1001,
self.corporation_1.corporation_id,
self.corporation_1.corporation_name,
)
AuthUtils.add_permission_to_user_by_name(
"auth.human_resources", self.user_manager
)
self.user_manager = User.objects.get(pk=self.user_manager.pk)
def test_no_pending_application(self):
# given manager of corporation 1 has permission
# when no application is pending for corporation 1
# return 0
self.assertEqual(
Application.objects.pending_requests_count_for_user(self.user_manager), 0
)
def test_single_pending_application(self):
# given manager of corporation 1 has permission
# when 1 application is pending for corporation 1
# return 1
Application.objects.create(
form=self.form_corporation_1, user=self.user_requestor
)
self.assertEqual(
Application.objects.pending_requests_count_for_user(self.user_manager), 1
)
def test_user_has_no_permission(self):
# given user has no permission
# when 1 application is pending
# return None
self.assertIsNone(
Application.objects.pending_requests_count_for_user(self.user_requestor)
)
def test_two_pending_applications_for_different_corporations_normal_manager(self):
# given manager of corporation 1 has permission
# when 1 application is pending for corporation 1
# and 1 application is pending for corporation 2
# return 1
Application.objects.create(
form=self.form_corporation_1, user=self.user_requestor
)
Application.objects.create(
form=self.form_corporation_2, user=self.user_requestor
)
self.assertEqual(
Application.objects.pending_requests_count_for_user(self.user_manager), 1
)
def test_two_pending_applications_for_different_corporations_manager_is_super(self):
# given manager of corporation 1 has permission
# when 1 application is pending for corporation 1
# and 1 application is pending for corporation 2
# return 1
Application.objects.create(
form=self.form_corporation_1, user=self.user_requestor
)
Application.objects.create(
form=self.form_corporation_2, user=self.user_requestor
)
superuser = User.objects.create_superuser(
"Superman", "superman@example.com", "password"
)
self.assertEqual(
Application.objects.pending_requests_count_for_user(superuser), 2
)

View File

@@ -6,16 +6,16 @@
# Translators: # Translators:
# Erik Kalkoken <erik.kalkoken@gmail.com>, 2020 # Erik Kalkoken <erik.kalkoken@gmail.com>, 2020
# Joel Falknau <ozirascal@gmail.com>, 2020 # Joel Falknau <ozirascal@gmail.com>, 2020
# Rounon Dax <rounon.dax@terra-nanotech.de>, 2020 # Peter Pfeufer <rounon.dax@terra-nanotech.de>, 2020
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-08 00:57+0000\n" "POT-Creation-Date: 2020-10-11 03:43+0000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Rounon Dax <rounon.dax@terra-nanotech.de>, 2020\n" "Last-Translator: Peter Pfeufer <rounon.dax@terra-nanotech.de>, 2020\n"
"Language-Team: German (https://www.transifex.com/alliance-auth/teams/107430/de/)\n" "Language-Team: German (https://www.transifex.com/alliance-auth/teams/107430/de/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -28,59 +28,59 @@ msgid "A main character is required to perform that action. Add one below."
msgstr "" msgstr ""
"Für diese Aktion wird ein Hauptcharacter benötigt. Bitte füge einen hinzu." "Für diese Aktion wird ein Hauptcharacter benötigt. Bitte füge einen hinzu."
#: allianceauth/authentication/forms.py:6 #: allianceauth/authentication/forms.py:5
msgid "Email" msgid "Email"
msgstr "E-Mail" msgstr "E-Mail"
#: allianceauth/authentication/models.py:76 #: allianceauth/authentication/models.py:78
msgid "State Changed"
msgstr "Status geändert"
#: allianceauth/authentication/models.py:77
#, python-format #, python-format
msgid "Your user state has been changed to %(state)s" msgid "State changed to: %s"
msgstr "Dein Nutzerstatus hat sich geändert zu %(state)s" msgstr "Status geändert zu %s"
#: allianceauth/authentication/models.py:79
#, python-format
msgid "Your user's state is now: %(state)s"
msgstr "Dein Nutzerstatus ist nun %(state)s"
#: allianceauth/authentication/templates/authentication/dashboard.html:5 #: allianceauth/authentication/templates/authentication/dashboard.html:5
#: allianceauth/authentication/templates/authentication/dashboard.html:8 #: allianceauth/authentication/templates/authentication/dashboard.html:8
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:11
msgid "Dashboard" msgid "Dashboard"
msgstr "Dashboard" msgstr "Dashboard"
#: allianceauth/authentication/templates/authentication/dashboard.html:17 #: allianceauth/authentication/templates/authentication/dashboard.html:18
#: allianceauth/corputils/templates/corputils/corpstats.html:116 #, python-format
#: allianceauth/corputils/templates/corputils/search.html:16 msgid ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22 "\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:83 " Main Character (State: %(state)s)\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:128 " "
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25 msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/view.html:32 "\n"
msgid "Main Character" "Hauptcharakter (Status: %(state)s)"
msgstr "Hauptcharakter"
#: allianceauth/authentication/templates/authentication/dashboard.html:77 #: allianceauth/authentication/templates/authentication/dashboard.html:81
msgid "No main character set." msgid "No main character set."
msgstr "Kein Hauptcharakter gesetzt." msgstr "Kein Hauptcharakter gesetzt."
#: allianceauth/authentication/templates/authentication/dashboard.html:84 #: allianceauth/authentication/templates/authentication/dashboard.html:88
msgid "Add Character" msgid "Add Character"
msgstr "Charakter hinzufügen" msgstr "Charakter hinzufügen"
#: allianceauth/authentication/templates/authentication/dashboard.html:88 #: allianceauth/authentication/templates/authentication/dashboard.html:92
msgid "Change Main" msgid "Change Main"
msgstr "Hauptcharakter ändern" msgstr "Hauptcharakter ändern"
#: allianceauth/authentication/templates/authentication/dashboard.html:97 #: allianceauth/authentication/templates/authentication/dashboard.html:101
msgid "Group Memberships" msgid "Group Memberships"
msgstr "Gruppen" msgstr "Gruppen"
#: allianceauth/authentication/templates/authentication/dashboard.html:117 #: allianceauth/authentication/templates/authentication/dashboard.html:121
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:41 #: allianceauth/hrapplications/templates/hrapplications/view.html:41
msgid "Characters" msgid "Characters"
msgstr "Charaktere" msgstr "Charaktere"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:129
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
@@ -89,13 +89,13 @@ msgstr "Charaktere"
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
#: allianceauth/authentication/templates/authentication/dashboard.html:126 #: allianceauth/authentication/templates/authentication/dashboard.html:130
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:46 #: allianceauth/hrapplications/templates/hrapplications/view.html:46
msgid "Corp" msgid "Corp"
msgstr "Corp" msgstr "Corp"
#: allianceauth/authentication/templates/authentication/dashboard.html:127 #: allianceauth/authentication/templates/authentication/dashboard.html:131
#: allianceauth/corputils/templates/corputils/corpstats.html:77 #: allianceauth/corputils/templates/corputils/corpstats.html:77
#: allianceauth/hrapplications/templates/hrapplications/view.html:47 #: allianceauth/hrapplications/templates/hrapplications/view.html:47
msgid "Alliance" msgid "Alliance"
@@ -168,11 +168,11 @@ msgstr ""
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "Authentifizierung mit dem ausgewählten Charakter nicht möglich." msgstr "Authentifizierung mit dem ausgewählten Charakter nicht möglich."
#: allianceauth/authentication/views.py:148 #: allianceauth/authentication/views.py:146
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "Token zur Registrierung ist abgelaufen." msgstr "Token zur Registrierung ist abgelaufen."
#: allianceauth/authentication/views.py:200 #: allianceauth/authentication/views.py:201
msgid "" msgid ""
"Sent confirmation email. Please follow the link to confirm your email " "Sent confirmation email. Please follow the link to confirm your email "
"address." "address."
@@ -180,12 +180,12 @@ msgstr ""
"Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur " "Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur "
"Bestätigung." "Bestätigung."
#: allianceauth/authentication/views.py:205 #: allianceauth/authentication/views.py:206
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "" msgstr ""
"Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren." "Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren."
#: allianceauth/authentication/views.py:210 #: allianceauth/authentication/views.py:211
msgid "Registraion of new accounts it not allowed at this time." msgid "Registraion of new accounts it not allowed at this time."
msgstr "Registrierung von neuen Konten ist zur Zeit nicht erlaubt." msgstr "Registrierung von neuen Konten ist zur Zeit nicht erlaubt."
@@ -236,8 +236,8 @@ msgstr "Letzes Update:"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
msgid "Character" msgid "Character"
msgstr "Charakter" msgstr "Charakter"
@@ -259,6 +259,16 @@ msgstr "Corporation"
msgid "Killboard" msgid "Killboard"
msgstr "Killboard" msgstr "Killboard"
#: allianceauth/corputils/templates/corputils/corpstats.html:116
#: allianceauth/corputils/templates/corputils/search.html:16
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "Hauptcharakter"
#: allianceauth/corputils/templates/corputils/corpstats.html:117 #: allianceauth/corputils/templates/corputils/corpstats.html:117
#: allianceauth/corputils/templates/corputils/search.html:17 #: allianceauth/corputils/templates/corputils/search.html:17
msgid "Main Corporation" msgid "Main Corporation"
@@ -542,6 +552,11 @@ msgstr "Flottenteilnahme registriert."
msgid "FAT link has expired." msgid "FAT link has expired."
msgstr "FAT-Link ist abgelaufen." msgstr "FAT-Link ist abgelaufen."
#: allianceauth/groupmanagement/auth_hooks.py:16
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
msgid "Group Management"
msgstr "Gruppenverwaltung"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
msgid "Audit Log" msgid "Audit Log"
@@ -594,8 +609,8 @@ msgid "Portrait"
msgstr "Portrait" msgstr "Portrait"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
msgid "Organization" msgid "Organization"
msgstr "Organization" msgstr "Organization"
@@ -614,7 +629,7 @@ msgstr "Gruppenmitgliedschaft"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:15 #: allianceauth/templates/allianceauth/side-menu.html:16
msgid "Groups" msgid "Groups"
msgstr "Gruppen" msgstr "Gruppen"
@@ -628,7 +643,7 @@ msgstr "Beschreibung"
#: allianceauth/hrapplications/templates/hrapplications/management.html:85 #: allianceauth/hrapplications/templates/hrapplications/management.html:85
#: allianceauth/hrapplications/templates/hrapplications/management.html:130 #: allianceauth/hrapplications/templates/hrapplications/management.html:130
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/srp/templates/srp/data.html:97 #: allianceauth/srp/templates/srp/data.html:98
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
@@ -658,8 +673,8 @@ msgid "Audit Members"
msgstr "Mitglieder Protokoll" msgstr "Mitglieder Protokoll"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
msgid "Copy Direrct Join Link" msgid "Copy Direct Join Link"
msgstr "" msgstr "Direktlink kopieren"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
msgid "No groups to list." msgid "No groups to list."
@@ -690,37 +705,37 @@ msgstr "Keine Gruppen verfügbar"
msgid "Groups Management" msgid "Groups Management"
msgstr "Gruppenverwaltung" msgstr "Gruppenverwaltung"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
msgid "Join Requests" msgid "Join Requests"
msgstr "Beitrittsgesuche" msgstr "Beitrittsgesuche"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
msgid "Leave Requests" msgid "Leave Requests"
msgstr "Austrittsgesuche" msgstr "Austrittsgesuche"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "Gruppen" msgstr "Gruppen"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
msgid "Accept" msgid "Accept"
msgstr "Akzeptieren" msgstr "Akzeptieren"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
#: allianceauth/hrapplications/templates/hrapplications/view.html:85 #: allianceauth/hrapplications/templates/hrapplications/view.html:85
msgid "Reject" msgid "Reject"
msgstr "Ablehnen" msgstr "Ablehnen"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
msgid "No group add requests." msgid "No group add requests."
msgstr "Keine Gruppenbeitrittsanfragen." msgstr "Keine Gruppenbeitrittsanfragen."
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
msgid "No group leave requests." msgid "No group leave requests."
msgstr "Keine Gruppenaustrittsanfragen" msgstr "Keine Gruppenaustrittsanfragen"
@@ -728,11 +743,6 @@ msgstr "Keine Gruppenaustrittsanfragen"
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "Toggle Navigation" msgstr "Toggle Navigation"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
#: allianceauth/templates/allianceauth/side-menu.html:23
msgid "Group Management"
msgstr "Gruppenverwaltung"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
msgid "Group Requests" msgid "Group Requests"
msgstr "Gruppenanfragen" msgstr "Gruppenanfragen"
@@ -741,26 +751,26 @@ msgstr "Gruppenanfragen"
msgid "Group Membership" msgid "Group Membership"
msgstr "Gruppenmitgliedschaft" msgstr "Gruppenmitgliedschaft"
#: allianceauth/groupmanagement/views.py:166 #: allianceauth/groupmanagement/views.py:162
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "Benutzer %(user)s von Gruppe %(group)s entfernt." msgstr "Benutzer %(user)s von Gruppe %(group)s entfernt."
#: allianceauth/groupmanagement/views.py:168 #: allianceauth/groupmanagement/views.py:164
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "Benutzer existiert nicht in dieser Gruppe" msgstr "Benutzer existiert nicht in dieser Gruppe"
#: allianceauth/groupmanagement/views.py:171 #: allianceauth/groupmanagement/views.py:167
msgid "Group does not exist" msgid "Group does not exist"
msgstr "Gruppe existiert nicht" msgstr "Gruppe existiert nicht"
#: allianceauth/groupmanagement/views.py:198 #: allianceauth/groupmanagement/views.py:194
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s zugestimmt." msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s zugestimmt."
#: allianceauth/groupmanagement/views.py:205 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:238 #: allianceauth/groupmanagement/views.py:234
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
@@ -769,18 +779,18 @@ msgstr ""
"Bei der Bearbeitung des Beitrittsgesuchs von %(mainchar)s zur Gruppe " "Bei der Bearbeitung des Beitrittsgesuchs von %(mainchar)s zur Gruppe "
"%(group)s ist ein unbehandelter Fehler aufgetreten." "%(group)s ist ein unbehandelter Fehler aufgetreten."
#: allianceauth/groupmanagement/views.py:231 #: allianceauth/groupmanagement/views.py:227
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s abgelehnt." msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s abgelehnt."
#: allianceauth/groupmanagement/views.py:267 #: allianceauth/groupmanagement/views.py:263
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s akzeptiert." msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s akzeptiert."
#: allianceauth/groupmanagement/views.py:273 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:307 #: allianceauth/groupmanagement/views.py:303
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
@@ -789,60 +799,60 @@ msgstr ""
"Bei der Bearbeitung des Austrittsgesuchs von %(mainchar)s für Gruppe " "Bei der Bearbeitung des Austrittsgesuchs von %(mainchar)s für Gruppe "
"%(group)s ist ein unbehandelter Fehler aufgetreten." "%(group)s ist ein unbehandelter Fehler aufgetreten."
#: allianceauth/groupmanagement/views.py:300 #: allianceauth/groupmanagement/views.py:296
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s abgelehnt." msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s abgelehnt."
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:342
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:354
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "Du kannst dieser Gruppe nicht beitreten" msgstr "Du kannst dieser Gruppe nicht beitreten"
#: allianceauth/groupmanagement/views.py:352 #: allianceauth/groupmanagement/views.py:348
msgid "You are already a member of that group." msgid "You are already a member of that group."
msgstr "Du bist bereits Mitglied dieser Gruppe." msgstr "Du bist bereits Mitglied dieser Gruppe."
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:363
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "Du hast Dich bereits für diese Gruppe beworben." msgstr "Du hast Dich bereits für diese Gruppe beworben."
#: allianceauth/groupmanagement/views.py:370 #: allianceauth/groupmanagement/views.py:366
#: allianceauth/groupmanagement/views.py:408 #: allianceauth/groupmanagement/views.py:404
#: allianceauth/hrapplications/templates/hrapplications/management.html:37 #: allianceauth/hrapplications/templates/hrapplications/management.html:37
#: allianceauth/hrapplications/templates/hrapplications/management.html:72 #: allianceauth/hrapplications/templates/hrapplications/management.html:72
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:144 #: allianceauth/hrapplications/templates/hrapplications/management.html:144
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
#: allianceauth/hrapplications/templates/hrapplications/view.html:20 #: allianceauth/hrapplications/templates/hrapplications/view.html:20
#: allianceauth/srp/templates/srp/data.html:125 #: allianceauth/srp/templates/srp/data.html:134
#: allianceauth/srp/templates/srp/management.html:81 #: allianceauth/srp/templates/srp/management.html:81
msgid "Pending" msgid "Pending"
msgstr "Beantragt" msgstr "Beantragt"
#: allianceauth/groupmanagement/views.py:376 #: allianceauth/groupmanagement/views.py:372
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "Beitritt zur Gruppe %(group)s beantragt." msgstr "Beitritt zur Gruppe %(group)s beantragt."
#: allianceauth/groupmanagement/views.py:387 #: allianceauth/groupmanagement/views.py:383
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "Du kannst diese Gruppe nicht verlassen" msgstr "Du kannst diese Gruppe nicht verlassen"
#: allianceauth/groupmanagement/views.py:392 #: allianceauth/groupmanagement/views.py:388
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "Du bist kein Mitglied dieser Gruppe" msgstr "Du bist kein Mitglied dieser Gruppe"
#: allianceauth/groupmanagement/views.py:401 #: allianceauth/groupmanagement/views.py:397
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "Du hast bereits ein ausstehendes Austrittsgesuch für diese Gruppe." msgstr "Du hast bereits ein ausstehendes Austrittsgesuch für diese Gruppe."
#: allianceauth/groupmanagement/views.py:414 #: allianceauth/groupmanagement/views.py:410
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "Austrittsgesuch für Gruppe %(group)s gesendet." msgstr "Austrittsgesuch für Gruppe %(group)s gesendet."
#: allianceauth/hrapplications/auth_hooks.py:10 #: allianceauth/hrapplications/auth_hooks.py:13
msgid "Applications" msgid "Applications"
msgstr "Bewerbungen" msgstr "Bewerbungen"
@@ -899,7 +909,7 @@ msgstr "Benutzername"
#: allianceauth/hrapplications/templates/hrapplications/management.html:131 #: allianceauth/hrapplications/templates/hrapplications/management.html:131
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
#: allianceauth/hrapplications/templates/hrapplications/view.html:75 #: allianceauth/hrapplications/templates/hrapplications/view.html:75
#: allianceauth/srp/templates/srp/data.html:99 #: allianceauth/srp/templates/srp/data.html:100
#: allianceauth/srp/templates/srp/management.html:46 #: allianceauth/srp/templates/srp/management.html:46
msgid "Actions" msgid "Actions"
msgstr "Aktionen" msgstr "Aktionen"
@@ -909,7 +919,7 @@ msgstr "Aktionen"
#: allianceauth/hrapplications/templates/hrapplications/management.html:147 #: allianceauth/hrapplications/templates/hrapplications/management.html:147
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
#: allianceauth/hrapplications/templates/hrapplications/view.html:16 #: allianceauth/hrapplications/templates/hrapplications/view.html:16
#: allianceauth/srp/templates/srp/data.html:117 #: allianceauth/srp/templates/srp/data.html:126
msgid "Approved" msgid "Approved"
msgstr "Akzeptiert" msgstr "Akzeptiert"
@@ -917,7 +927,7 @@ msgstr "Akzeptiert"
#: allianceauth/hrapplications/templates/hrapplications/management.html:104 #: allianceauth/hrapplications/templates/hrapplications/management.html:104
#: allianceauth/hrapplications/templates/hrapplications/management.html:149 #: allianceauth/hrapplications/templates/hrapplications/management.html:149
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
#: allianceauth/srp/templates/srp/data.html:121 #: allianceauth/srp/templates/srp/data.html:130
msgid "Rejected" msgid "Rejected"
msgstr "Abgelehnt" msgstr "Abgelehnt"
@@ -1023,7 +1033,7 @@ msgstr "Ungelesen"
#: allianceauth/notifications/templates/notifications/list.html:18 #: allianceauth/notifications/templates/notifications/list.html:18
msgid "Read" msgid "Read"
msgstr "Lesen" msgstr "Gelesen"
#: allianceauth/notifications/templates/notifications/list.html:22 #: allianceauth/notifications/templates/notifications/list.html:22
msgid "Mark All Read" msgid "Mark All Read"
@@ -1300,23 +1310,54 @@ msgstr "Passwort"
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "Passwort muss mindestens 8 Zeichen lang sein" msgstr "Passwort muss mindestens 8 Zeichen lang sein"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23 #: allianceauth/services/modules/discord/models.py:225
msgid "Discord Account Disabled"
msgstr "Discord Konto deaktiviert"
#: allianceauth/services/modules/discord/models.py:227
msgid ""
"Your Discord account was disabeled automatically by Auth. If you think this "
"was a mistake, please contact an admin."
msgstr ""
"Dein Discord Konto wurde automatisch durch Auth deaktiviert. Wenn Du glaubst"
" dies war ein Fehler, kontaktiere bitte einen Administrator."
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
msgid "Join the Discord server"
msgstr "Discord Server beitreten"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
msgid "Leave- and rejoin the Discord Server (Reset)"
msgstr "Discord Server verlassen und wieder beitreten (Zurücksetzen)"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
msgid "Leave the Discord server"
msgstr "Discord Server verlassen"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
msgid "Link Discord Server" msgid "Link Discord Server"
msgstr "Verbinde Discord Server" msgstr "Verbinde Discord Server"
#: allianceauth/services/modules/discord/views.py:26 #: allianceauth/services/modules/discord/views.py:30
msgid "Deactivated Discord account." msgid "Deactivated Discord account."
msgstr "Discord Konto deaktiviert." msgstr "Discord Konto deaktiviert."
#: allianceauth/services/modules/discord/views.py:29 #: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:41 #: allianceauth/services/modules/discord/views.py:59
#: allianceauth/services/modules/discord/views.py:65
msgid "An error occurred while processing your Discord account." msgid "An error occurred while processing your Discord account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Discord Kontos." msgstr "Es gab einen Fehler bei der Verarbeitung Deines Discord Kontos."
#: allianceauth/services/modules/discord/views.py:62 #: allianceauth/services/modules/discord/views.py:102
msgid "Activated Discord account." msgid "Your Discord account has been successfully activated."
msgstr "Discord Konto aktiviert." msgstr "Dein Discord Konto wurde erfolgreich aktiviert."
#: allianceauth/services/modules/discord/views.py:108
msgid ""
"An error occurred while trying to activate your Discord account. Please try "
"again."
msgstr ""
"Es gab einen Fehler während der Aktivierung Deines Discord Kontos. Bitte "
"versuche es noch einmal."
#: allianceauth/services/modules/discourse/views.py:37 #: allianceauth/services/modules/discourse/views.py:37
msgid "You are not authorized to access Discourse." msgid "You are not authorized to access Discourse."
@@ -1587,7 +1628,7 @@ msgstr "Dienst"
msgid "Domain" msgid "Domain"
msgstr "Domain" msgstr "Domain"
#: allianceauth/srp/auth_hooks.py:9 #: allianceauth/srp/auth_hooks.py:12
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "Schiffserstattung" msgstr "Schiffserstattung"
@@ -1601,7 +1642,7 @@ msgstr "Flottenzeit"
msgid "Fleet Doctrine" msgid "Fleet Doctrine"
msgstr "Flottendoktrin" msgstr "Flottendoktrin"
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89 #: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
msgid "Additional Info" msgid "Additional Info"
msgstr "Zusätzliche Info" msgstr "Zusätzliche Info"
@@ -1630,65 +1671,65 @@ msgstr "SRP-Flotte erstellen"
msgid "Give this link to the line members" msgid "Give this link to the line members"
msgstr "Gib diesen Link an Deine Piloten weiter" msgstr "Gib diesen Link an Deine Piloten weiter"
#: allianceauth/srp/templates/srp/data.html:48 #: allianceauth/srp/templates/srp/data.html:49
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "SRP-Flotte Daten" msgstr "SRP-Flotte Daten"
#: allianceauth/srp/templates/srp/data.html:53 #: allianceauth/srp/templates/srp/data.html:54
msgid "Mark Incomplete" msgid "Mark Incomplete"
msgstr "Als unvollständig markieren" msgstr "Als unvollständig markieren"
#: allianceauth/srp/templates/srp/data.html:57 #: allianceauth/srp/templates/srp/data.html:58
msgid "Mark Completed" msgid "Mark Completed"
msgstr "Als vollständig markieren" msgstr "Als vollständig markieren"
#: allianceauth/srp/templates/srp/data.html:69 #: allianceauth/srp/templates/srp/data.html:70
#: allianceauth/srp/templates/srp/data.html:145 #: allianceauth/srp/templates/srp/data.html:156
msgid "Total Losses:" msgid "Total Losses:"
msgstr "Verluste insgesamt:" msgstr "Verluste insgesamt:"
#: allianceauth/srp/templates/srp/data.html:70 #: allianceauth/srp/templates/srp/data.html:71
#: allianceauth/srp/templates/srp/data.html:146 #: allianceauth/srp/templates/srp/data.html:157
#: allianceauth/srp/templates/srp/management.html:30 #: allianceauth/srp/templates/srp/management.html:30
msgid "Total ISK Cost:" msgid "Total ISK Cost:"
msgstr "ISK-Kosten insgesamt:" msgstr "ISK-Kosten insgesamt:"
#: allianceauth/srp/templates/srp/data.html:78 #: allianceauth/srp/templates/srp/data.html:79
#: allianceauth/srp/templates/srp/data.html:154 #: allianceauth/srp/templates/srp/data.html:165
msgid "Are you sure you want to delete SRP requests?" msgid "Are you sure you want to delete SRP requests?"
msgstr "Bist Du sicher das Du SRP Anfragen löschen willst?" msgstr "Bist Du sicher das Du SRP Anfragen löschen willst?"
#: allianceauth/srp/templates/srp/data.html:87 #: allianceauth/srp/templates/srp/data.html:88
msgid "Pilot Name" msgid "Pilot Name"
msgstr "Name des Piloten" msgstr "Name des Piloten"
#: allianceauth/srp/templates/srp/data.html:88 #: allianceauth/srp/templates/srp/data.html:89
msgid "Killboard Link" msgid "Killboard Link"
msgstr "Killboard Link" msgstr "Killboard Link"
#: allianceauth/srp/templates/srp/data.html:90 #: allianceauth/srp/templates/srp/data.html:91
msgid "Ship Type" msgid "Ship Type"
msgstr "Schiffstyp" msgstr "Schiffstyp"
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:92
msgid "Killboard Loss Amt" msgid "Killboard Loss Amt"
msgstr "Summe Killboard Verluste" msgstr "Summe Killboard Verluste"
#: allianceauth/srp/templates/srp/data.html:92 #: allianceauth/srp/templates/srp/data.html:93
msgid "SRP ISK Cost" msgid "SRP ISK Cost"
msgstr "SRP ISK-Kosten" msgstr "SRP ISK-Kosten"
#: allianceauth/srp/templates/srp/data.html:93 #: allianceauth/srp/templates/srp/data.html:94
msgid "Click value to edit Enter to save & next ESC to cancel" msgid "Click value to edit Enter to save & next ESC to cancel"
msgstr "" msgstr ""
"Klicke auf den Wert um diesen zu bearbeiten, Enter zum Speichern und um zum " "Klicke auf den Wert um diesen zu bearbeiten, Enter zum Speichern und um zum "
"nächsten Wert zu springen, ESC zum Beenden." "nächsten Wert zu springen, ESC zum Beenden."
#: allianceauth/srp/templates/srp/data.html:96 #: allianceauth/srp/templates/srp/data.html:97
msgid "Post Time" msgid "Post Time"
msgstr "Veröffentlichungszeit" msgstr "Veröffentlichungszeit"
#: allianceauth/srp/templates/srp/data.html:163 #: allianceauth/srp/templates/srp/data.html:174
msgid "No SRP requests for this fleet." msgid "No SRP requests for this fleet."
msgstr "Keine SRP Anfragen für diese Flotte." msgstr "Keine SRP Anfragen für diese Flotte."
@@ -1884,32 +1925,30 @@ msgid "Current"
msgstr "Aktuell" msgstr "Aktuell"
#: allianceauth/templates/allianceauth/admin-status/overview.html:40 #: allianceauth/templates/allianceauth/admin-status/overview.html:40
msgid "Latest Major" msgid "Latest Stable"
msgstr "Aktuellste Hauptversion" msgstr "Aktuellste stabile Version"
#: allianceauth/templates/allianceauth/admin-status/overview.html:46 #: allianceauth/templates/allianceauth/admin-status/overview.html:46
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
msgid "Update available" msgid "Update available"
msgstr "Update verfügbar" msgstr "Update verfügbar"
#: allianceauth/templates/allianceauth/admin-status/overview.html:50 #: allianceauth/templates/allianceauth/admin-status/overview.html:51
msgid "Latest Minor" msgid "Latest Pre-Release"
msgstr "Aktuellste Unterversion" msgstr "Aktuellste Testversion"
#: allianceauth/templates/allianceauth/admin-status/overview.html:60 #: allianceauth/templates/allianceauth/admin-status/overview.html:57
msgid "Latest Patch" msgid "Pre-Release available"
msgstr "Aktuellste Patchversion" msgstr "Testversion verfügbar"
#: allianceauth/templates/allianceauth/admin-status/overview.html:73 #: allianceauth/templates/allianceauth/admin-status/overview.html:65
msgid "Task Queue" msgid "Task Queue"
msgstr "Warteschlange" msgstr "Warteschlange"
#: allianceauth/templates/allianceauth/admin-status/overview.html:90 #: allianceauth/templates/allianceauth/admin-status/overview.html:82
msgid "Error retrieving task queue length" msgid "Error retrieving task queue length"
msgstr "Fehler beim Ermitteln der Warteschlange." msgstr "Fehler beim Ermitteln der Warteschlange."
#: allianceauth/templates/allianceauth/admin-status/overview.html:92 #: allianceauth/templates/allianceauth/admin-status/overview.html:84
#, python-format #, python-format
msgid "%(tasks)s task" msgid "%(tasks)s task"
msgid_plural "%(tasks)s tasks" msgid_plural "%(tasks)s tasks"

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-08 00:57+0000\n" "POT-Creation-Date: 2020-10-01 02:59+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -22,59 +22,57 @@ msgstr ""
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "" msgstr ""
#: allianceauth/authentication/forms.py:6 #: allianceauth/authentication/forms.py:5
msgid "Email" msgid "Email"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:76 #: allianceauth/authentication/models.py:78
msgid "State Changed" #, python-format
msgid "State changed to: %s"
msgstr "" msgstr ""
#: allianceauth/authentication/models.py:77 #: allianceauth/authentication/models.py:79
#, python-format #, python-format
msgid "Your user state has been changed to %(state)s" msgid "Your user's state is now: %(state)s"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:5 #: allianceauth/authentication/templates/authentication/dashboard.html:5
#: allianceauth/authentication/templates/authentication/dashboard.html:8 #: allianceauth/authentication/templates/authentication/dashboard.html:8
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:11
msgid "Dashboard" msgid "Dashboard"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:17 #: allianceauth/authentication/templates/authentication/dashboard.html:18
#: allianceauth/corputils/templates/corputils/corpstats.html:116 #, python-format
#: allianceauth/corputils/templates/corputils/search.html:16 msgid ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22 "\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:83 " Main Character (State: %(state)s)\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:128 " "
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:77 #: allianceauth/authentication/templates/authentication/dashboard.html:81
msgid "No main character set." msgid "No main character set."
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:84 #: allianceauth/authentication/templates/authentication/dashboard.html:88
msgid "Add Character" msgid "Add Character"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:88 #: allianceauth/authentication/templates/authentication/dashboard.html:92
msgid "Change Main" msgid "Change Main"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:97 #: allianceauth/authentication/templates/authentication/dashboard.html:101
msgid "Group Memberships" msgid "Group Memberships"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:117 #: allianceauth/authentication/templates/authentication/dashboard.html:121
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:41 #: allianceauth/hrapplications/templates/hrapplications/view.html:41
msgid "Characters" msgid "Characters"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:129
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
@@ -83,13 +81,13 @@ msgstr ""
msgid "Name" msgid "Name"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:126 #: allianceauth/authentication/templates/authentication/dashboard.html:130
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:46 #: allianceauth/hrapplications/templates/hrapplications/view.html:46
msgid "Corp" msgid "Corp"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:127 #: allianceauth/authentication/templates/authentication/dashboard.html:131
#: allianceauth/corputils/templates/corputils/corpstats.html:77 #: allianceauth/corputils/templates/corputils/corpstats.html:77
#: allianceauth/hrapplications/templates/hrapplications/view.html:47 #: allianceauth/hrapplications/templates/hrapplications/view.html:47
msgid "Alliance" msgid "Alliance"
@@ -156,22 +154,22 @@ msgstr ""
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:148 #: allianceauth/authentication/views.py:146
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:200 #: allianceauth/authentication/views.py:201
msgid "" msgid ""
"Sent confirmation email. Please follow the link to confirm your email " "Sent confirmation email. Please follow the link to confirm your email "
"address." "address."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:205 #: allianceauth/authentication/views.py:206
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "" msgstr ""
#: allianceauth/authentication/views.py:210 #: allianceauth/authentication/views.py:211
msgid "Registraion of new accounts it not allowed at this time." msgid "Registration of new accounts is not allowed at this time."
msgstr "" msgstr ""
#: allianceauth/corputils/auth_hooks.py:10 #: allianceauth/corputils/auth_hooks.py:10
@@ -221,8 +219,8 @@ msgstr ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
msgid "Character" msgid "Character"
msgstr "" msgstr ""
@@ -244,6 +242,16 @@ msgstr ""
msgid "Killboard" msgid "Killboard"
msgstr "" msgstr ""
#: allianceauth/corputils/templates/corputils/corpstats.html:116
#: allianceauth/corputils/templates/corputils/search.html:16
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr ""
#: allianceauth/corputils/templates/corputils/corpstats.html:117 #: allianceauth/corputils/templates/corputils/corpstats.html:117
#: allianceauth/corputils/templates/corputils/search.html:17 #: allianceauth/corputils/templates/corputils/search.html:17
msgid "Main Corporation" msgid "Main Corporation"
@@ -527,6 +535,11 @@ msgstr ""
msgid "FAT link has expired." msgid "FAT link has expired."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/auth_hooks.py:16
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
msgid "Group Management"
msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
msgid "Audit Log" msgid "Audit Log"
@@ -579,8 +592,8 @@ msgid "Portrait"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
msgid "Organization" msgid "Organization"
msgstr "" msgstr ""
@@ -599,7 +612,7 @@ msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:15 #: allianceauth/templates/allianceauth/side-menu.html:16
msgid "Groups" msgid "Groups"
msgstr "" msgstr ""
@@ -613,7 +626,7 @@ msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:85 #: allianceauth/hrapplications/templates/hrapplications/management.html:85
#: allianceauth/hrapplications/templates/hrapplications/management.html:130 #: allianceauth/hrapplications/templates/hrapplications/management.html:130
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/srp/templates/srp/data.html:97 #: allianceauth/srp/templates/srp/data.html:98
msgid "Status" msgid "Status"
msgstr "" msgstr ""
@@ -643,7 +656,7 @@ msgid "Audit Members"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
msgid "Copy Direrct Join Link" msgid "Copy Direct Join Link"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
@@ -675,37 +688,37 @@ msgstr ""
msgid "Groups Management" msgid "Groups Management"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
msgid "Join Requests" msgid "Join Requests"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
msgid "Leave Requests" msgid "Leave Requests"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
msgid "Accept" msgid "Accept"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
#: allianceauth/hrapplications/templates/hrapplications/view.html:85 #: allianceauth/hrapplications/templates/hrapplications/view.html:85
msgid "Reject" msgid "Reject"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
msgid "No group add requests." msgid "No group add requests."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
msgid "No group leave requests." msgid "No group leave requests."
msgstr "" msgstr ""
@@ -713,11 +726,6 @@ msgstr ""
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
#: allianceauth/templates/allianceauth/side-menu.html:23
msgid "Group Management"
msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
msgid "Group Requests" msgid "Group Requests"
msgstr "" msgstr ""
@@ -726,104 +734,104 @@ msgstr ""
msgid "Group Membership" msgid "Group Membership"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:166 #: allianceauth/groupmanagement/views.py:162
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:168 #: allianceauth/groupmanagement/views.py:164
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:171 #: allianceauth/groupmanagement/views.py:167
msgid "Group does not exist" msgid "Group does not exist"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:198 #: allianceauth/groupmanagement/views.py:194
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:205 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:238 #: allianceauth/groupmanagement/views.py:234
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s." "%(mainchar)s to %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:231 #: allianceauth/groupmanagement/views.py:227
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:267 #: allianceauth/groupmanagement/views.py:263
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:273 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:307 #: allianceauth/groupmanagement/views.py:303
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:300 #: allianceauth/groupmanagement/views.py:296
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:342
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:354
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:352 #: allianceauth/groupmanagement/views.py:348
msgid "You are already a member of that group." msgid "You are already a member of that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:363
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:370 #: allianceauth/groupmanagement/views.py:366
#: allianceauth/groupmanagement/views.py:408 #: allianceauth/groupmanagement/views.py:404
#: allianceauth/hrapplications/templates/hrapplications/management.html:37 #: allianceauth/hrapplications/templates/hrapplications/management.html:37
#: allianceauth/hrapplications/templates/hrapplications/management.html:72 #: allianceauth/hrapplications/templates/hrapplications/management.html:72
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:144 #: allianceauth/hrapplications/templates/hrapplications/management.html:144
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
#: allianceauth/hrapplications/templates/hrapplications/view.html:20 #: allianceauth/hrapplications/templates/hrapplications/view.html:20
#: allianceauth/srp/templates/srp/data.html:125 #: allianceauth/srp/templates/srp/data.html:128
#: allianceauth/srp/templates/srp/management.html:81 #: allianceauth/srp/templates/srp/management.html:81
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:376 #: allianceauth/groupmanagement/views.py:372
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:387 #: allianceauth/groupmanagement/views.py:383
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:392 #: allianceauth/groupmanagement/views.py:388
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:401 #: allianceauth/groupmanagement/views.py:397
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:414 #: allianceauth/groupmanagement/views.py:410
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "" msgstr ""
#: allianceauth/hrapplications/auth_hooks.py:10 #: allianceauth/hrapplications/auth_hooks.py:13
msgid "Applications" msgid "Applications"
msgstr "" msgstr ""
@@ -880,7 +888,7 @@ msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:131 #: allianceauth/hrapplications/templates/hrapplications/management.html:131
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
#: allianceauth/hrapplications/templates/hrapplications/view.html:75 #: allianceauth/hrapplications/templates/hrapplications/view.html:75
#: allianceauth/srp/templates/srp/data.html:99 #: allianceauth/srp/templates/srp/data.html:100
#: allianceauth/srp/templates/srp/management.html:46 #: allianceauth/srp/templates/srp/management.html:46
msgid "Actions" msgid "Actions"
msgstr "" msgstr ""
@@ -890,7 +898,7 @@ msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:147 #: allianceauth/hrapplications/templates/hrapplications/management.html:147
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
#: allianceauth/hrapplications/templates/hrapplications/view.html:16 #: allianceauth/hrapplications/templates/hrapplications/view.html:16
#: allianceauth/srp/templates/srp/data.html:117 #: allianceauth/srp/templates/srp/data.html:120
msgid "Approved" msgid "Approved"
msgstr "" msgstr ""
@@ -898,7 +906,7 @@ msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:104 #: allianceauth/hrapplications/templates/hrapplications/management.html:104
#: allianceauth/hrapplications/templates/hrapplications/management.html:149 #: allianceauth/hrapplications/templates/hrapplications/management.html:149
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
#: allianceauth/srp/templates/srp/data.html:121 #: allianceauth/srp/templates/srp/data.html:124
msgid "Rejected" msgid "Rejected"
msgstr "" msgstr ""
@@ -1281,22 +1289,49 @@ msgstr ""
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "" msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23 #: allianceauth/services/modules/discord/models.py:225
msgid "Discord Account Disabled"
msgstr ""
#: allianceauth/services/modules/discord/models.py:227
msgid ""
"Your Discord account was disabled automatically by Auth. If you think this "
"was a mistake, please contact an admin."
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
msgid "Join the Discord server"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
msgid "Leave- and rejoin the Discord Server (Reset)"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
msgid "Leave the Discord server"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
msgid "Link Discord Server" msgid "Link Discord Server"
msgstr "" msgstr ""
#: allianceauth/services/modules/discord/views.py:26 #: allianceauth/services/modules/discord/views.py:30
msgid "Deactivated Discord account." msgid "Deactivated Discord account."
msgstr "" msgstr ""
#: allianceauth/services/modules/discord/views.py:29 #: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:41 #: allianceauth/services/modules/discord/views.py:59
#: allianceauth/services/modules/discord/views.py:65
msgid "An error occurred while processing your Discord account." msgid "An error occurred while processing your Discord account."
msgstr "" msgstr ""
#: allianceauth/services/modules/discord/views.py:62 #: allianceauth/services/modules/discord/views.py:102
msgid "Activated Discord account." msgid "Your Discord account has been successfully activated."
msgstr ""
#: allianceauth/services/modules/discord/views.py:108
msgid ""
"An error occurred while trying to activate your Discord account. Please try "
"again."
msgstr "" msgstr ""
#: allianceauth/services/modules/discourse/views.py:37 #: allianceauth/services/modules/discourse/views.py:37
@@ -1560,7 +1595,7 @@ msgstr ""
msgid "Domain" msgid "Domain"
msgstr "" msgstr ""
#: allianceauth/srp/auth_hooks.py:9 #: allianceauth/srp/auth_hooks.py:12
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "" msgstr ""
@@ -1572,7 +1607,7 @@ msgstr ""
msgid "Fleet Doctrine" msgid "Fleet Doctrine"
msgstr "" msgstr ""
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89 #: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
msgid "Additional Info" msgid "Additional Info"
msgstr "" msgstr ""
@@ -1601,63 +1636,63 @@ msgstr ""
msgid "Give this link to the line members" msgid "Give this link to the line members"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:48 #: allianceauth/srp/templates/srp/data.html:49
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:53 #: allianceauth/srp/templates/srp/data.html:54
msgid "Mark Incomplete" msgid "Mark Incomplete"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:57 #: allianceauth/srp/templates/srp/data.html:58
msgid "Mark Completed" msgid "Mark Completed"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:69 #: allianceauth/srp/templates/srp/data.html:70
#: allianceauth/srp/templates/srp/data.html:145 #: allianceauth/srp/templates/srp/data.html:150
msgid "Total Losses:" msgid "Total Losses:"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:70 #: allianceauth/srp/templates/srp/data.html:71
#: allianceauth/srp/templates/srp/data.html:146 #: allianceauth/srp/templates/srp/data.html:151
#: allianceauth/srp/templates/srp/management.html:30 #: allianceauth/srp/templates/srp/management.html:30
msgid "Total ISK Cost:" msgid "Total ISK Cost:"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:78 #: allianceauth/srp/templates/srp/data.html:79
#: allianceauth/srp/templates/srp/data.html:154 #: allianceauth/srp/templates/srp/data.html:159
msgid "Are you sure you want to delete SRP requests?" msgid "Are you sure you want to delete SRP requests?"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:87 #: allianceauth/srp/templates/srp/data.html:88
msgid "Pilot Name" msgid "Pilot Name"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:88 #: allianceauth/srp/templates/srp/data.html:89
msgid "Killboard Link" msgid "Killboard Link"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:90 #: allianceauth/srp/templates/srp/data.html:91
msgid "Ship Type" msgid "Ship Type"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:92
msgid "Killboard Loss Amt" msgid "Killboard Loss Amt"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:92 #: allianceauth/srp/templates/srp/data.html:93
msgid "SRP ISK Cost" msgid "SRP ISK Cost"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:93 #: allianceauth/srp/templates/srp/data.html:94
msgid "Click value to edit Enter to save & next ESC to cancel" msgid "Click value to edit Enter to save & next ESC to cancel"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:96 #: allianceauth/srp/templates/srp/data.html:97
msgid "Post Time" msgid "Post Time"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:163 #: allianceauth/srp/templates/srp/data.html:168
msgid "No SRP requests for this fleet." msgid "No SRP requests for this fleet."
msgstr "" msgstr ""
@@ -1848,32 +1883,30 @@ msgid "Current"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:40 #: allianceauth/templates/allianceauth/admin-status/overview.html:40
msgid "Latest Major" msgid "Latest Stable"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:46 #: allianceauth/templates/allianceauth/admin-status/overview.html:46
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
msgid "Update available" msgid "Update available"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:50 #: allianceauth/templates/allianceauth/admin-status/overview.html:51
msgid "Latest Minor" msgid "Latest Pre-Release"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:60 #: allianceauth/templates/allianceauth/admin-status/overview.html:57
msgid "Latest Patch" msgid "Pre-Release available"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:73 #: allianceauth/templates/allianceauth/admin-status/overview.html:65
msgid "Task Queue" msgid "Task Queue"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:90 #: allianceauth/templates/allianceauth/admin-status/overview.html:82
msgid "Error retrieving task queue length" msgid "Error retrieving task queue length"
msgstr "" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:92 #: allianceauth/templates/allianceauth/admin-status/overview.html:84
#, python-format #, python-format
msgid "%(tasks)s task" msgid "%(tasks)s task"
msgid_plural "%(tasks)s tasks" msgid_plural "%(tasks)s tasks"

View File

@@ -4,17 +4,17 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Joel Falknau <ozirascal@gmail.com>, 2020
# frank1210 <francolopez_16@hotmail.com>, 2020 # frank1210 <francolopez_16@hotmail.com>, 2020
# Joel Falknau <ozirascal@gmail.com>, 2020
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-08 00:57+0000\n" "POT-Creation-Date: 2020-10-11 03:43+0000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: frank1210 <francolopez_16@hotmail.com>, 2020\n" "Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
"Language-Team: Spanish (https://www.transifex.com/alliance-auth/teams/107430/es/)\n" "Language-Team: Spanish (https://www.transifex.com/alliance-auth/teams/107430/es/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -27,59 +27,57 @@ msgid "A main character is required to perform that action. Add one below."
msgstr "" msgstr ""
"Un personaje principal es requerido para completar esta accion. Agregue uno" "Un personaje principal es requerido para completar esta accion. Agregue uno"
#: allianceauth/authentication/forms.py:6 #: allianceauth/authentication/forms.py:5
msgid "Email" msgid "Email"
msgstr "E-mail" msgstr "E-mail"
#: allianceauth/authentication/models.py:76 #: allianceauth/authentication/models.py:78
msgid "State Changed"
msgstr "Estado Cambiado"
#: allianceauth/authentication/models.py:77
#, python-format #, python-format
msgid "Your user state has been changed to %(state)s" msgid "State changed to: %s"
msgstr "Tu estado de usuario fue cambiado a %(state)s" msgstr ""
#: allianceauth/authentication/models.py:79
#, python-format
msgid "Your user's state is now: %(state)s"
msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:5 #: allianceauth/authentication/templates/authentication/dashboard.html:5
#: allianceauth/authentication/templates/authentication/dashboard.html:8 #: allianceauth/authentication/templates/authentication/dashboard.html:8
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:11
msgid "Dashboard" msgid "Dashboard"
msgstr "Pagina Principal" msgstr "Pagina Principal"
#: allianceauth/authentication/templates/authentication/dashboard.html:17 #: allianceauth/authentication/templates/authentication/dashboard.html:18
#: allianceauth/corputils/templates/corputils/corpstats.html:116 #, python-format
#: allianceauth/corputils/templates/corputils/search.html:16 msgid ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22 "\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:83 " Main Character (State: %(state)s)\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:128 " "
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25 msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "Personaje Principal"
#: allianceauth/authentication/templates/authentication/dashboard.html:77 #: allianceauth/authentication/templates/authentication/dashboard.html:81
msgid "No main character set." msgid "No main character set."
msgstr "No se ha seleccionado un personaje principal." msgstr "No se ha seleccionado un personaje principal."
#: allianceauth/authentication/templates/authentication/dashboard.html:84 #: allianceauth/authentication/templates/authentication/dashboard.html:88
msgid "Add Character" msgid "Add Character"
msgstr "Agregar Personaje" msgstr "Agregar Personaje"
#: allianceauth/authentication/templates/authentication/dashboard.html:88 #: allianceauth/authentication/templates/authentication/dashboard.html:92
msgid "Change Main" msgid "Change Main"
msgstr "Cambiar Personaje Principal" msgstr "Cambiar Personaje Principal"
#: allianceauth/authentication/templates/authentication/dashboard.html:97 #: allianceauth/authentication/templates/authentication/dashboard.html:101
msgid "Group Memberships" msgid "Group Memberships"
msgstr "" msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:117 #: allianceauth/authentication/templates/authentication/dashboard.html:121
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:41 #: allianceauth/hrapplications/templates/hrapplications/view.html:41
msgid "Characters" msgid "Characters"
msgstr "Personajes" msgstr "Personajes"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:129
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
@@ -88,13 +86,13 @@ msgstr "Personajes"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
#: allianceauth/authentication/templates/authentication/dashboard.html:126 #: allianceauth/authentication/templates/authentication/dashboard.html:130
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:46 #: allianceauth/hrapplications/templates/hrapplications/view.html:46
msgid "Corp" msgid "Corp"
msgstr "Corporación" msgstr "Corporación"
#: allianceauth/authentication/templates/authentication/dashboard.html:127 #: allianceauth/authentication/templates/authentication/dashboard.html:131
#: allianceauth/corputils/templates/corputils/corpstats.html:77 #: allianceauth/corputils/templates/corputils/corpstats.html:77
#: allianceauth/hrapplications/templates/hrapplications/view.html:47 #: allianceauth/hrapplications/templates/hrapplications/view.html:47
msgid "Alliance" msgid "Alliance"
@@ -163,24 +161,24 @@ msgstr ""
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "Imposible validar con el personaje seleccionado." msgstr "Imposible validar con el personaje seleccionado."
#: allianceauth/authentication/views.py:148 #: allianceauth/authentication/views.py:146
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "El token de registracion expiro." msgstr "El token de registracion expiro."
#: allianceauth/authentication/views.py:200 #: allianceauth/authentication/views.py:201
msgid "" msgid ""
"Sent confirmation email. Please follow the link to confirm your email " "Sent confirmation email. Please follow the link to confirm your email "
"address." "address."
msgstr "" msgstr ""
"Confirmacion de mail enviada. Por favor siga el enlace para confirmar " "Confirmacion de mail enviada. Por favor siga el enlace para confirmar "
#: allianceauth/authentication/views.py:205 #: allianceauth/authentication/views.py:206
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "" msgstr ""
"Se ha confirmado su direccion de mail. Por favor igrese su token para " "Se ha confirmado su direccion de mail. Por favor igrese su token para "
"continuar." "continuar."
#: allianceauth/authentication/views.py:210 #: allianceauth/authentication/views.py:211
msgid "Registraion of new accounts it not allowed at this time." msgid "Registraion of new accounts it not allowed at this time."
msgstr "Registracion de nuevas cuentas no es permitido por el momento." msgstr "Registracion de nuevas cuentas no es permitido por el momento."
@@ -231,8 +229,8 @@ msgstr "Ultima Actualizacion:"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
msgid "Character" msgid "Character"
msgstr "Personaje" msgstr "Personaje"
@@ -254,6 +252,16 @@ msgstr "Corporacion"
msgid "Killboard" msgid "Killboard"
msgstr "Killboard" msgstr "Killboard"
#: allianceauth/corputils/templates/corputils/corpstats.html:116
#: allianceauth/corputils/templates/corputils/search.html:16
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "Personaje Principal"
#: allianceauth/corputils/templates/corputils/corpstats.html:117 #: allianceauth/corputils/templates/corputils/corpstats.html:117
#: allianceauth/corputils/templates/corputils/search.html:17 #: allianceauth/corputils/templates/corputils/search.html:17
msgid "Main Corporation" msgid "Main Corporation"
@@ -538,6 +546,11 @@ msgstr "Participacion de flota registrada."
msgid "FAT link has expired." msgid "FAT link has expired."
msgstr "Enlace de participacion expirado." msgstr "Enlace de participacion expirado."
#: allianceauth/groupmanagement/auth_hooks.py:16
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
msgid "Group Management"
msgstr "Manejo de Grupo"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
msgid "Audit Log" msgid "Audit Log"
@@ -590,8 +603,8 @@ msgid "Portrait"
msgstr "Retrato" msgstr "Retrato"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
msgid "Organization" msgid "Organization"
msgstr "" msgstr ""
@@ -610,7 +623,7 @@ msgstr "Membresia de grupos"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:15 #: allianceauth/templates/allianceauth/side-menu.html:16
msgid "Groups" msgid "Groups"
msgstr "Grupos" msgstr "Grupos"
@@ -624,7 +637,7 @@ msgstr "Descripcion"
#: allianceauth/hrapplications/templates/hrapplications/management.html:85 #: allianceauth/hrapplications/templates/hrapplications/management.html:85
#: allianceauth/hrapplications/templates/hrapplications/management.html:130 #: allianceauth/hrapplications/templates/hrapplications/management.html:130
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/srp/templates/srp/data.html:97 #: allianceauth/srp/templates/srp/data.html:98
msgid "Status" msgid "Status"
msgstr "Estado" msgstr "Estado"
@@ -654,7 +667,7 @@ msgid "Audit Members"
msgstr "Auditar Miembros" msgstr "Auditar Miembros"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
msgid "Copy Direrct Join Link" msgid "Copy Direct Join Link"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
@@ -686,37 +699,37 @@ msgstr "No hay grupos disponibles"
msgid "Groups Management" msgid "Groups Management"
msgstr "Manejo de Grupos" msgstr "Manejo de Grupos"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
msgid "Join Requests" msgid "Join Requests"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
msgid "Leave Requests" msgid "Leave Requests"
msgstr "" msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "Grupo" msgstr "Grupo"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
msgid "Accept" msgid "Accept"
msgstr "Aceptar" msgstr "Aceptar"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
#: allianceauth/hrapplications/templates/hrapplications/view.html:85 #: allianceauth/hrapplications/templates/hrapplications/view.html:85
msgid "Reject" msgid "Reject"
msgstr "Rechazar" msgstr "Rechazar"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
msgid "No group add requests." msgid "No group add requests."
msgstr "No hay solicitudes de ingreso." msgstr "No hay solicitudes de ingreso."
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
msgid "No group leave requests." msgid "No group leave requests."
msgstr "No hay solicitudes paradejar el grupo." msgstr "No hay solicitudes paradejar el grupo."
@@ -724,11 +737,6 @@ msgstr "No hay solicitudes paradejar el grupo."
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "Navegacion" msgstr "Navegacion"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
#: allianceauth/templates/allianceauth/side-menu.html:23
msgid "Group Management"
msgstr "Manejo de Grupo"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
msgid "Group Requests" msgid "Group Requests"
msgstr "Solicitudes de Grupo" msgstr "Solicitudes de Grupo"
@@ -737,26 +745,26 @@ msgstr "Solicitudes de Grupo"
msgid "Group Membership" msgid "Group Membership"
msgstr "Membresia de Grupo" msgstr "Membresia de Grupo"
#: allianceauth/groupmanagement/views.py:166 #: allianceauth/groupmanagement/views.py:162
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "El usuario %(user)s fue removido del grupo %(group)s" msgstr "El usuario %(user)s fue removido del grupo %(group)s"
#: allianceauth/groupmanagement/views.py:168 #: allianceauth/groupmanagement/views.py:164
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "El usuario no existe en ese grupos" msgstr "El usuario no existe en ese grupos"
#: allianceauth/groupmanagement/views.py:171 #: allianceauth/groupmanagement/views.py:167
msgid "Group does not exist" msgid "Group does not exist"
msgstr "El grupo no existe" msgstr "El grupo no existe"
#: allianceauth/groupmanagement/views.py:198 #: allianceauth/groupmanagement/views.py:194
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "Solicitud aceptada de %(mainchar)s a %(group)s" msgstr "Solicitud aceptada de %(mainchar)s a %(group)s"
#: allianceauth/groupmanagement/views.py:205 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:238 #: allianceauth/groupmanagement/views.py:234
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
@@ -765,79 +773,79 @@ msgstr ""
"Ocurrio un error cuando se intento procesar la informacion de %(mainchar)s " "Ocurrio un error cuando se intento procesar la informacion de %(mainchar)s "
"al grupo %(group)s." "al grupo %(group)s."
#: allianceauth/groupmanagement/views.py:231 #: allianceauth/groupmanagement/views.py:227
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "Se rechazo la solicitud de %(mainchar)s al grupo %(group)s." msgstr "Se rechazo la solicitud de %(mainchar)s al grupo %(group)s."
#: allianceauth/groupmanagement/views.py:267 #: allianceauth/groupmanagement/views.py:263
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "Se acepto la solicitud de %(mainchar)s para dejar el grupo %(group)s." msgstr "Se acepto la solicitud de %(mainchar)s para dejar el grupo %(group)s."
#: allianceauth/groupmanagement/views.py:273 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:307 #: allianceauth/groupmanagement/views.py:303
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:300 #: allianceauth/groupmanagement/views.py:296
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
"Se rechazo la solicitud de %(mainchar)s para dejar el grupo %(group)s." "Se rechazo la solicitud de %(mainchar)s para dejar el grupo %(group)s."
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:342
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:354
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "No puedes unirte a ese grupo" msgstr "No puedes unirte a ese grupo"
#: allianceauth/groupmanagement/views.py:352 #: allianceauth/groupmanagement/views.py:348
msgid "You are already a member of that group." msgid "You are already a member of that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:363
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:370 #: allianceauth/groupmanagement/views.py:366
#: allianceauth/groupmanagement/views.py:408 #: allianceauth/groupmanagement/views.py:404
#: allianceauth/hrapplications/templates/hrapplications/management.html:37 #: allianceauth/hrapplications/templates/hrapplications/management.html:37
#: allianceauth/hrapplications/templates/hrapplications/management.html:72 #: allianceauth/hrapplications/templates/hrapplications/management.html:72
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:144 #: allianceauth/hrapplications/templates/hrapplications/management.html:144
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
#: allianceauth/hrapplications/templates/hrapplications/view.html:20 #: allianceauth/hrapplications/templates/hrapplications/view.html:20
#: allianceauth/srp/templates/srp/data.html:125 #: allianceauth/srp/templates/srp/data.html:134
#: allianceauth/srp/templates/srp/management.html:81 #: allianceauth/srp/templates/srp/management.html:81
msgid "Pending" msgid "Pending"
msgstr "Pendiente" msgstr "Pendiente"
#: allianceauth/groupmanagement/views.py:376 #: allianceauth/groupmanagement/views.py:372
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "Solicitud enviada al grupo %(group)s." msgstr "Solicitud enviada al grupo %(group)s."
#: allianceauth/groupmanagement/views.py:387 #: allianceauth/groupmanagement/views.py:383
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "No puedes dejar el grupos" msgstr "No puedes dejar el grupos"
#: allianceauth/groupmanagement/views.py:392 #: allianceauth/groupmanagement/views.py:388
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "No eres miembro de ese grupo" msgstr "No eres miembro de ese grupo"
#: allianceauth/groupmanagement/views.py:401 #: allianceauth/groupmanagement/views.py:397
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "" msgstr ""
#: allianceauth/groupmanagement/views.py:414 #: allianceauth/groupmanagement/views.py:410
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "Solicitaste dejar el grupo %(group)s." msgstr "Solicitaste dejar el grupo %(group)s."
#: allianceauth/hrapplications/auth_hooks.py:10 #: allianceauth/hrapplications/auth_hooks.py:13
msgid "Applications" msgid "Applications"
msgstr "Solicitudes" msgstr "Solicitudes"
@@ -894,7 +902,7 @@ msgstr "Usuario"
#: allianceauth/hrapplications/templates/hrapplications/management.html:131 #: allianceauth/hrapplications/templates/hrapplications/management.html:131
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
#: allianceauth/hrapplications/templates/hrapplications/view.html:75 #: allianceauth/hrapplications/templates/hrapplications/view.html:75
#: allianceauth/srp/templates/srp/data.html:99 #: allianceauth/srp/templates/srp/data.html:100
#: allianceauth/srp/templates/srp/management.html:46 #: allianceauth/srp/templates/srp/management.html:46
msgid "Actions" msgid "Actions"
msgstr "Acciones" msgstr "Acciones"
@@ -904,7 +912,7 @@ msgstr "Acciones"
#: allianceauth/hrapplications/templates/hrapplications/management.html:147 #: allianceauth/hrapplications/templates/hrapplications/management.html:147
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
#: allianceauth/hrapplications/templates/hrapplications/view.html:16 #: allianceauth/hrapplications/templates/hrapplications/view.html:16
#: allianceauth/srp/templates/srp/data.html:117 #: allianceauth/srp/templates/srp/data.html:126
msgid "Approved" msgid "Approved"
msgstr "Aprovado" msgstr "Aprovado"
@@ -912,7 +920,7 @@ msgstr "Aprovado"
#: allianceauth/hrapplications/templates/hrapplications/management.html:104 #: allianceauth/hrapplications/templates/hrapplications/management.html:104
#: allianceauth/hrapplications/templates/hrapplications/management.html:149 #: allianceauth/hrapplications/templates/hrapplications/management.html:149
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
#: allianceauth/srp/templates/srp/data.html:121 #: allianceauth/srp/templates/srp/data.html:130
msgid "Rejected" msgid "Rejected"
msgstr "Rechazado" msgstr "Rechazado"
@@ -1295,22 +1303,49 @@ msgstr "Contraseña"
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "La contraseña tiene que tener 8 caracteres de largo minimo" msgstr "La contraseña tiene que tener 8 caracteres de largo minimo"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23 #: allianceauth/services/modules/discord/models.py:225
msgid "Discord Account Disabled"
msgstr ""
#: allianceauth/services/modules/discord/models.py:227
msgid ""
"Your Discord account was disabeled automatically by Auth. If you think this "
"was a mistake, please contact an admin."
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
msgid "Join the Discord server"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
msgid "Leave- and rejoin the Discord Server (Reset)"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
msgid "Leave the Discord server"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
msgid "Link Discord Server" msgid "Link Discord Server"
msgstr "Enlace a servidor de Discord" msgstr "Enlace a servidor de Discord"
#: allianceauth/services/modules/discord/views.py:26 #: allianceauth/services/modules/discord/views.py:30
msgid "Deactivated Discord account." msgid "Deactivated Discord account."
msgstr "" msgstr ""
#: allianceauth/services/modules/discord/views.py:29 #: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:41 #: allianceauth/services/modules/discord/views.py:59
#: allianceauth/services/modules/discord/views.py:65
msgid "An error occurred while processing your Discord account." msgid "An error occurred while processing your Discord account."
msgstr "" msgstr ""
#: allianceauth/services/modules/discord/views.py:62 #: allianceauth/services/modules/discord/views.py:102
msgid "Activated Discord account." msgid "Your Discord account has been successfully activated."
msgstr ""
#: allianceauth/services/modules/discord/views.py:108
msgid ""
"An error occurred while trying to activate your Discord account. Please try "
"again."
msgstr "" msgstr ""
#: allianceauth/services/modules/discourse/views.py:37 #: allianceauth/services/modules/discourse/views.py:37
@@ -1575,7 +1610,7 @@ msgstr "Servicio"
msgid "Domain" msgid "Domain"
msgstr "Dominio" msgstr "Dominio"
#: allianceauth/srp/auth_hooks.py:9 #: allianceauth/srp/auth_hooks.py:12
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "Reemplazo de Nave" msgstr "Reemplazo de Nave"
@@ -1589,7 +1624,7 @@ msgstr "Hora de flota"
msgid "Fleet Doctrine" msgid "Fleet Doctrine"
msgstr "Doctrina" msgstr "Doctrina"
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89 #: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
msgid "Additional Info" msgid "Additional Info"
msgstr "Informacion Adicional" msgstr "Informacion Adicional"
@@ -1618,63 +1653,63 @@ msgstr "Crear SRP"
msgid "Give this link to the line members" msgid "Give this link to the line members"
msgstr "Entregar este enlace a los miembros" msgstr "Entregar este enlace a los miembros"
#: allianceauth/srp/templates/srp/data.html:48 #: allianceauth/srp/templates/srp/data.html:49
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "Informacion de SRP de la flota" msgstr "Informacion de SRP de la flota"
#: allianceauth/srp/templates/srp/data.html:53 #: allianceauth/srp/templates/srp/data.html:54
msgid "Mark Incomplete" msgid "Mark Incomplete"
msgstr "Marcar como Incompleto" msgstr "Marcar como Incompleto"
#: allianceauth/srp/templates/srp/data.html:57 #: allianceauth/srp/templates/srp/data.html:58
msgid "Mark Completed" msgid "Mark Completed"
msgstr "Marcar como Completo" msgstr "Marcar como Completo"
#: allianceauth/srp/templates/srp/data.html:69 #: allianceauth/srp/templates/srp/data.html:70
#: allianceauth/srp/templates/srp/data.html:145 #: allianceauth/srp/templates/srp/data.html:156
msgid "Total Losses:" msgid "Total Losses:"
msgstr "Perdidas Totales:" msgstr "Perdidas Totales:"
#: allianceauth/srp/templates/srp/data.html:70 #: allianceauth/srp/templates/srp/data.html:71
#: allianceauth/srp/templates/srp/data.html:146 #: allianceauth/srp/templates/srp/data.html:157
#: allianceauth/srp/templates/srp/management.html:30 #: allianceauth/srp/templates/srp/management.html:30
msgid "Total ISK Cost:" msgid "Total ISK Cost:"
msgstr "Costo Total:" msgstr "Costo Total:"
#: allianceauth/srp/templates/srp/data.html:78 #: allianceauth/srp/templates/srp/data.html:79
#: allianceauth/srp/templates/srp/data.html:154 #: allianceauth/srp/templates/srp/data.html:165
msgid "Are you sure you want to delete SRP requests?" msgid "Are you sure you want to delete SRP requests?"
msgstr "Estas seguro que quiere borrar las solicitudes de SRP" msgstr "Estas seguro que quiere borrar las solicitudes de SRP"
#: allianceauth/srp/templates/srp/data.html:87 #: allianceauth/srp/templates/srp/data.html:88
msgid "Pilot Name" msgid "Pilot Name"
msgstr "Nombre del Piloto" msgstr "Nombre del Piloto"
#: allianceauth/srp/templates/srp/data.html:88 #: allianceauth/srp/templates/srp/data.html:89
msgid "Killboard Link" msgid "Killboard Link"
msgstr "Enlace de la Muerte" msgstr "Enlace de la Muerte"
#: allianceauth/srp/templates/srp/data.html:90 #: allianceauth/srp/templates/srp/data.html:91
msgid "Ship Type" msgid "Ship Type"
msgstr "Tipo" msgstr "Tipo"
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:92
msgid "Killboard Loss Amt" msgid "Killboard Loss Amt"
msgstr "Monto de la perdida en ZKB" msgstr "Monto de la perdida en ZKB"
#: allianceauth/srp/templates/srp/data.html:92 #: allianceauth/srp/templates/srp/data.html:93
msgid "SRP ISK Cost" msgid "SRP ISK Cost"
msgstr "Costo del SRP" msgstr "Costo del SRP"
#: allianceauth/srp/templates/srp/data.html:93 #: allianceauth/srp/templates/srp/data.html:94
msgid "Click value to edit Enter to save & next ESC to cancel" msgid "Click value to edit Enter to save & next ESC to cancel"
msgstr "" msgstr ""
#: allianceauth/srp/templates/srp/data.html:96 #: allianceauth/srp/templates/srp/data.html:97
msgid "Post Time" msgid "Post Time"
msgstr "Tiempo" msgstr "Tiempo"
#: allianceauth/srp/templates/srp/data.html:163 #: allianceauth/srp/templates/srp/data.html:174
msgid "No SRP requests for this fleet." msgid "No SRP requests for this fleet."
msgstr "No hay solicitudes de SRP para esta flota." msgstr "No hay solicitudes de SRP para esta flota."
@@ -1866,32 +1901,30 @@ msgid "Current"
msgstr "Actual" msgstr "Actual"
#: allianceauth/templates/allianceauth/admin-status/overview.html:40 #: allianceauth/templates/allianceauth/admin-status/overview.html:40
msgid "Latest Major" msgid "Latest Stable"
msgstr "Ultimo Importante" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:46 #: allianceauth/templates/allianceauth/admin-status/overview.html:46
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
msgid "Update available" msgid "Update available"
msgstr "Actualizacion Disponible" msgstr "Actualizacion Disponible"
#: allianceauth/templates/allianceauth/admin-status/overview.html:50 #: allianceauth/templates/allianceauth/admin-status/overview.html:51
msgid "Latest Minor" msgid "Latest Pre-Release"
msgstr "Ultimo no importante" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:60 #: allianceauth/templates/allianceauth/admin-status/overview.html:57
msgid "Latest Patch" msgid "Pre-Release available"
msgstr "Ultimo Parche" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:73 #: allianceauth/templates/allianceauth/admin-status/overview.html:65
msgid "Task Queue" msgid "Task Queue"
msgstr "Cola de Tareas" msgstr "Cola de Tareas"
#: allianceauth/templates/allianceauth/admin-status/overview.html:90 #: allianceauth/templates/allianceauth/admin-status/overview.html:82
msgid "Error retrieving task queue length" msgid "Error retrieving task queue length"
msgstr "Error al conseguir la cola de tareas" msgstr "Error al conseguir la cola de tareas"
#: allianceauth/templates/allianceauth/admin-status/overview.html:92 #: allianceauth/templates/allianceauth/admin-status/overview.html:84
#, python-format #, python-format
msgid "%(tasks)s task" msgid "%(tasks)s task"
msgid_plural "%(tasks)s tasks" msgid_plural "%(tasks)s tasks"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -4,19 +4,19 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Lahty <js03js70@gmail.com>, 2020 # None None <khd1226543@gmail.com>, 2020
# Kim Hyundong <khd1226543@gmail.com>, 2020
# Seowon Jung <seowon@hawaii.edu>, 2020
# Olgeda Choi <undead.choi@gmail.com>, 2020 # Olgeda Choi <undead.choi@gmail.com>, 2020
# Seowon Jung <seowon@hawaii.edu>, 2020
# Lahty <js03js70@gmail.com>, 2020
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-08 00:57+0000\n" "POT-Creation-Date: 2020-10-11 03:43+0000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Olgeda Choi <undead.choi@gmail.com>, 2020\n" "Last-Translator: Lahty <js03js70@gmail.com>, 2020\n"
"Language-Team: Korean (Korea) (https://www.transifex.com/alliance-auth/teams/107430/ko_KR/)\n" "Language-Team: Korean (Korea) (https://www.transifex.com/alliance-auth/teams/107430/ko_KR/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -28,59 +28,60 @@ msgstr ""
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "해당 기능을 수행하려면 주 캐릭터가 요구됨. 아래에 하나를 추가하시오." msgstr "해당 기능을 수행하려면 주 캐릭터가 요구됨. 아래에 하나를 추가하시오."
#: allianceauth/authentication/forms.py:6 #: allianceauth/authentication/forms.py:5
msgid "Email" msgid "Email"
msgstr "이메일" msgstr "이메일"
#: allianceauth/authentication/models.py:76 #: allianceauth/authentication/models.py:78
msgid "State Changed"
msgstr "상태 변경됨"
#: allianceauth/authentication/models.py:77
#, python-format #, python-format
msgid "Your user state has been changed to %(state)s" msgid "State changed to: %s"
msgstr "사용자의 상태가 %(state)s변경됨" msgstr "상태가 %s로 변경됐습니다."
#: allianceauth/authentication/models.py:79
#, python-format
msgid "Your user's state is now: %(state)s"
msgstr "사용자의 상태는 %(state)s입니다."
#: allianceauth/authentication/templates/authentication/dashboard.html:5 #: allianceauth/authentication/templates/authentication/dashboard.html:5
#: allianceauth/authentication/templates/authentication/dashboard.html:8 #: allianceauth/authentication/templates/authentication/dashboard.html:8
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:11
msgid "Dashboard" msgid "Dashboard"
msgstr "대시보드" msgstr "대시보드"
#: allianceauth/authentication/templates/authentication/dashboard.html:17 #: allianceauth/authentication/templates/authentication/dashboard.html:18
#: allianceauth/corputils/templates/corputils/corpstats.html:116 #, python-format
#: allianceauth/corputils/templates/corputils/search.html:16 msgid ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22 "\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:83 " Main Character (State: %(state)s)\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:128 " "
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25 msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/view.html:32 "\n"
msgid "Main Character" " 메인 캐릭터 (상태: %(state)s)\n"
msgstr "주 캐릭터" " "
#: allianceauth/authentication/templates/authentication/dashboard.html:77 #: allianceauth/authentication/templates/authentication/dashboard.html:81
msgid "No main character set." msgid "No main character set."
msgstr "주 캐릭터가 지정되지 않음" msgstr "주 캐릭터가 지정되지 않음"
#: allianceauth/authentication/templates/authentication/dashboard.html:84 #: allianceauth/authentication/templates/authentication/dashboard.html:88
msgid "Add Character" msgid "Add Character"
msgstr "캐릭터 추가" msgstr "캐릭터 추가"
#: allianceauth/authentication/templates/authentication/dashboard.html:88 #: allianceauth/authentication/templates/authentication/dashboard.html:92
msgid "Change Main" msgid "Change Main"
msgstr "주 캐릭터 변경" msgstr "주 캐릭터 변경"
#: allianceauth/authentication/templates/authentication/dashboard.html:97 #: allianceauth/authentication/templates/authentication/dashboard.html:101
msgid "Group Memberships" msgid "Group Memberships"
msgstr "그룹 멤버쉽" msgstr "그룹 멤버쉽"
#: allianceauth/authentication/templates/authentication/dashboard.html:117 #: allianceauth/authentication/templates/authentication/dashboard.html:121
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:41 #: allianceauth/hrapplications/templates/hrapplications/view.html:41
msgid "Characters" msgid "Characters"
msgstr "캐릭터" msgstr "캐릭터"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:129
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
@@ -89,13 +90,13 @@ msgstr "캐릭터"
msgid "Name" msgid "Name"
msgstr "이름" msgstr "이름"
#: allianceauth/authentication/templates/authentication/dashboard.html:126 #: allianceauth/authentication/templates/authentication/dashboard.html:130
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:46 #: allianceauth/hrapplications/templates/hrapplications/view.html:46
msgid "Corp" msgid "Corp"
msgstr "콥" msgstr "콥"
#: allianceauth/authentication/templates/authentication/dashboard.html:127 #: allianceauth/authentication/templates/authentication/dashboard.html:131
#: allianceauth/corputils/templates/corputils/corpstats.html:77 #: allianceauth/corputils/templates/corputils/corpstats.html:77
#: allianceauth/hrapplications/templates/hrapplications/view.html:47 #: allianceauth/hrapplications/templates/hrapplications/view.html:47
msgid "Alliance" msgid "Alliance"
@@ -151,32 +152,32 @@ msgstr "주 캐릭터가 %(char)s로 변경됨"
#: allianceauth/authentication/views.py:89 #: allianceauth/authentication/views.py:89
#, python-format #, python-format
msgid "Added %(name)s to your account." msgid "Added %(name)s to your account."
msgstr "%(name)s을(를) 계정에 추가함" msgstr "계정에 %(name)s를 추가했습니다."
#: allianceauth/authentication/views.py:91 #: allianceauth/authentication/views.py:91
#, python-format #, python-format
msgid "Failed to add %(name)s to your account: they already have an account." msgid "Failed to add %(name)s to your account: they already have an account."
msgstr "%(name)s을(를) 계정에 추가하는데 실패함. 이미 추가되어있음." msgstr "계정에 %(name)s를 추가하지 못했습니다. 이미 추가된 계정입니다."
#: allianceauth/authentication/views.py:130 #: allianceauth/authentication/views.py:130
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "선택한 캐릭터로 인증을 수행할 수 없음" msgstr "선택한 캐릭터로 인증을 수행할 수 없음"
#: allianceauth/authentication/views.py:148 #: allianceauth/authentication/views.py:146
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "등록토큰 만료" msgstr "등록토큰 만료"
#: allianceauth/authentication/views.py:200 #: allianceauth/authentication/views.py:201
msgid "" msgid ""
"Sent confirmation email. Please follow the link to confirm your email " "Sent confirmation email. Please follow the link to confirm your email "
"address." "address."
msgstr "확인 메일 전송됨. 다음 링크를 눌러 이메일 주소를 확인하세요." msgstr "확인 메일 전송됨. 다음 링크를 눌러 이메일 주소를 확인하세요."
#: allianceauth/authentication/views.py:205 #: allianceauth/authentication/views.py:206
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "이메일 주소가 확인되었습니다. 로그인 해주세요." msgstr "이메일 주소가 확인되었습니다. 로그인 해주세요."
#: allianceauth/authentication/views.py:210 #: allianceauth/authentication/views.py:211
msgid "Registraion of new accounts it not allowed at this time." msgid "Registraion of new accounts it not allowed at this time."
msgstr "현재 새로운 계정 등록은 받지않습니다." msgstr "현재 새로운 계정 등록은 받지않습니다."
@@ -227,8 +228,8 @@ msgstr "마지막 업데이트"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
msgid "Character" msgid "Character"
msgstr "캐릭터" msgstr "캐릭터"
@@ -250,6 +251,16 @@ msgstr "콥"
msgid "Killboard" msgid "Killboard"
msgstr "킬보드" msgstr "킬보드"
#: allianceauth/corputils/templates/corputils/corpstats.html:116
#: allianceauth/corputils/templates/corputils/search.html:16
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "주 캐릭터"
#: allianceauth/corputils/templates/corputils/corpstats.html:117 #: allianceauth/corputils/templates/corputils/corpstats.html:117
#: allianceauth/corputils/templates/corputils/search.html:17 #: allianceauth/corputils/templates/corputils/search.html:17
msgid "Main Corporation" msgid "Main Corporation"
@@ -531,6 +542,11 @@ msgstr "플릿 참여 등록됨"
msgid "FAT link has expired." msgid "FAT link has expired."
msgstr "플릿활동추적 링크 기한만료" msgstr "플릿활동추적 링크 기한만료"
#: allianceauth/groupmanagement/auth_hooks.py:16
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
msgid "Group Management"
msgstr "그룹 관리"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
msgid "Audit Log" msgid "Audit Log"
@@ -583,8 +599,8 @@ msgid "Portrait"
msgstr "포트레잇" msgstr "포트레잇"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
msgid "Organization" msgid "Organization"
msgstr "조직" msgstr "조직"
@@ -603,7 +619,7 @@ msgstr "그룹 멤버쉽"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:15 #: allianceauth/templates/allianceauth/side-menu.html:16
msgid "Groups" msgid "Groups"
msgstr "그룹" msgstr "그룹"
@@ -617,7 +633,7 @@ msgstr "설명"
#: allianceauth/hrapplications/templates/hrapplications/management.html:85 #: allianceauth/hrapplications/templates/hrapplications/management.html:85
#: allianceauth/hrapplications/templates/hrapplications/management.html:130 #: allianceauth/hrapplications/templates/hrapplications/management.html:130
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/srp/templates/srp/data.html:97 #: allianceauth/srp/templates/srp/data.html:98
msgid "Status" msgid "Status"
msgstr "상태" msgstr "상태"
@@ -647,8 +663,8 @@ msgid "Audit Members"
msgstr "멤버 검사" msgstr "멤버 검사"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
msgid "Copy Direrct Join Link" msgid "Copy Direct Join Link"
msgstr "" msgstr "직접 참여 링크 복사"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
msgid "No groups to list." msgid "No groups to list."
@@ -679,37 +695,37 @@ msgstr "사용 가능한 그룹 없음."
msgid "Groups Management" msgid "Groups Management"
msgstr "그룹 관리" msgstr "그룹 관리"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
msgid "Join Requests" msgid "Join Requests"
msgstr "가입 요청" msgstr "가입 요청"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
msgid "Leave Requests" msgid "Leave Requests"
msgstr "탈퇴 요청" msgstr "탈퇴 요청"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "그룹" msgstr "그룹"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
msgid "Accept" msgid "Accept"
msgstr "수락" msgstr "수락"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
#: allianceauth/hrapplications/templates/hrapplications/view.html:85 #: allianceauth/hrapplications/templates/hrapplications/view.html:85
msgid "Reject" msgid "Reject"
msgstr "거절" msgstr "거절"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
msgid "No group add requests." msgid "No group add requests."
msgstr "가입 요청 없음" msgstr "가입 요청 없음"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
msgid "No group leave requests." msgid "No group leave requests."
msgstr "탈퇴 요청 없음" msgstr "탈퇴 요청 없음"
@@ -717,11 +733,6 @@ msgstr "탈퇴 요청 없음"
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "네비게이션 전환" msgstr "네비게이션 전환"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
#: allianceauth/templates/allianceauth/side-menu.html:23
msgid "Group Management"
msgstr "그룹 관리"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
msgid "Group Requests" msgid "Group Requests"
msgstr "그룹 요청" msgstr "그룹 요청"
@@ -730,104 +741,104 @@ msgstr "그룹 요청"
msgid "Group Membership" msgid "Group Membership"
msgstr "그룹 멤버쉽" msgstr "그룹 멤버쉽"
#: allianceauth/groupmanagement/views.py:166 #: allianceauth/groupmanagement/views.py:162
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "유저 %(user)s이(가) %(group)s에서 제거됨." msgstr "유저 %(user)s이(가) %(group)s에서 제거됨."
#: allianceauth/groupmanagement/views.py:168 #: allianceauth/groupmanagement/views.py:164
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "유저가 해당 그룹에 존재하지 않음." msgstr "유저가 해당 그룹에 존재하지 않음."
#: allianceauth/groupmanagement/views.py:171 #: allianceauth/groupmanagement/views.py:167
msgid "Group does not exist" msgid "Group does not exist"
msgstr "그룹이 존재하지 않음." msgstr "그룹이 존재하지 않음."
#: allianceauth/groupmanagement/views.py:198 #: allianceauth/groupmanagement/views.py:194
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "%(mainchar)s의 %(group)s 그룹 신청 수락" msgstr "%(mainchar)s의 %(group)s 그룹 신청 수락"
#: allianceauth/groupmanagement/views.py:205 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:238 #: allianceauth/groupmanagement/views.py:234
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s." "%(mainchar)s to %(group)s."
msgstr "%(mainchar)s의 %(group)s 그룹 신청을 처리하는 중 알 수 없는 에러 발생" msgstr "%(mainchar)s의 %(group)s 그룹 신청을 처리하는 중 알 수 없는 에러 발생"
#: allianceauth/groupmanagement/views.py:231 #: allianceauth/groupmanagement/views.py:227
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "%(mainchar)s의 %(group)s 그룹 신청 거절" msgstr "%(mainchar)s의 %(group)s 그룹 신청 거절"
#: allianceauth/groupmanagement/views.py:267 #: allianceauth/groupmanagement/views.py:263
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴 수락" msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴 수락"
#: allianceauth/groupmanagement/views.py:273 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:307 #: allianceauth/groupmanagement/views.py:303
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴를 처리하는 중 알 수 없는 에러 발생" msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴를 처리하는 중 알 수 없는 에러 발생"
#: allianceauth/groupmanagement/views.py:300 #: allianceauth/groupmanagement/views.py:296
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴 거절" msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴 거절"
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:342
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:354
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "해당 그룹에 참여할 수 없습니다." msgstr "해당 그룹에 참여할 수 없습니다."
#: allianceauth/groupmanagement/views.py:352 #: allianceauth/groupmanagement/views.py:348
msgid "You are already a member of that group." msgid "You are already a member of that group."
msgstr "이미 해당 그룹에 가입되어 있습니다." msgstr "이미 해당 그룹에 가입되어 있습니다."
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:363
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "해당 그룹에 대한 참여신청이 보류되었습니다." msgstr "해당 그룹에 대한 참여신청이 보류되었습니다."
#: allianceauth/groupmanagement/views.py:370 #: allianceauth/groupmanagement/views.py:366
#: allianceauth/groupmanagement/views.py:408 #: allianceauth/groupmanagement/views.py:404
#: allianceauth/hrapplications/templates/hrapplications/management.html:37 #: allianceauth/hrapplications/templates/hrapplications/management.html:37
#: allianceauth/hrapplications/templates/hrapplications/management.html:72 #: allianceauth/hrapplications/templates/hrapplications/management.html:72
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:144 #: allianceauth/hrapplications/templates/hrapplications/management.html:144
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
#: allianceauth/hrapplications/templates/hrapplications/view.html:20 #: allianceauth/hrapplications/templates/hrapplications/view.html:20
#: allianceauth/srp/templates/srp/data.html:125 #: allianceauth/srp/templates/srp/data.html:134
#: allianceauth/srp/templates/srp/management.html:81 #: allianceauth/srp/templates/srp/management.html:81
msgid "Pending" msgid "Pending"
msgstr "보류 중" msgstr "보류 중"
#: allianceauth/groupmanagement/views.py:376 #: allianceauth/groupmanagement/views.py:372
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "%(group)s그룹에 지원하였음." msgstr "%(group)s그룹에 지원하였음."
#: allianceauth/groupmanagement/views.py:387 #: allianceauth/groupmanagement/views.py:383
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "해당 그룹을 떠날 수 없습니다." msgstr "해당 그룹을 떠날 수 없습니다."
#: allianceauth/groupmanagement/views.py:392 #: allianceauth/groupmanagement/views.py:388
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "해당그룹의 멤버가 아닙니다." msgstr "해당그룹의 멤버가 아닙니다."
#: allianceauth/groupmanagement/views.py:401 #: allianceauth/groupmanagement/views.py:397
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "해당 그룹의 탈퇴 신청이 접수된 상태입니다." msgstr "해당 그룹의 탈퇴 신청이 접수된 상태입니다."
#: allianceauth/groupmanagement/views.py:414 #: allianceauth/groupmanagement/views.py:410
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "%(group)s그룹의 탈퇴가 신청됨." msgstr "%(group)s그룹의 탈퇴가 신청됨."
#: allianceauth/hrapplications/auth_hooks.py:10 #: allianceauth/hrapplications/auth_hooks.py:13
msgid "Applications" msgid "Applications"
msgstr "지원" msgstr "지원"
@@ -884,7 +895,7 @@ msgstr "사용자명"
#: allianceauth/hrapplications/templates/hrapplications/management.html:131 #: allianceauth/hrapplications/templates/hrapplications/management.html:131
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
#: allianceauth/hrapplications/templates/hrapplications/view.html:75 #: allianceauth/hrapplications/templates/hrapplications/view.html:75
#: allianceauth/srp/templates/srp/data.html:99 #: allianceauth/srp/templates/srp/data.html:100
#: allianceauth/srp/templates/srp/management.html:46 #: allianceauth/srp/templates/srp/management.html:46
msgid "Actions" msgid "Actions"
msgstr "활동" msgstr "활동"
@@ -894,7 +905,7 @@ msgstr "활동"
#: allianceauth/hrapplications/templates/hrapplications/management.html:147 #: allianceauth/hrapplications/templates/hrapplications/management.html:147
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
#: allianceauth/hrapplications/templates/hrapplications/view.html:16 #: allianceauth/hrapplications/templates/hrapplications/view.html:16
#: allianceauth/srp/templates/srp/data.html:117 #: allianceauth/srp/templates/srp/data.html:126
msgid "Approved" msgid "Approved"
msgstr "승인" msgstr "승인"
@@ -902,7 +913,7 @@ msgstr "승인"
#: allianceauth/hrapplications/templates/hrapplications/management.html:104 #: allianceauth/hrapplications/templates/hrapplications/management.html:104
#: allianceauth/hrapplications/templates/hrapplications/management.html:149 #: allianceauth/hrapplications/templates/hrapplications/management.html:149
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
#: allianceauth/srp/templates/srp/data.html:121 #: allianceauth/srp/templates/srp/data.html:130
msgid "Rejected" msgid "Rejected"
msgstr "거절" msgstr "거절"
@@ -1285,23 +1296,50 @@ msgstr "비밀번호"
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "비밀번호는 8글자 이상이어야 합니다." msgstr "비밀번호는 8글자 이상이어야 합니다."
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23 #: allianceauth/services/modules/discord/models.py:225
msgid "Discord Account Disabled"
msgstr "디스코드 계정 비활성화"
#: allianceauth/services/modules/discord/models.py:227
msgid ""
"Your Discord account was disabeled automatically by Auth. If you think this "
"was a mistake, please contact an admin."
msgstr "Auth에 의해 자동으로 디스코드 계정이 비활성화됐습니다. 원치 않는 사항일 경우, 관리자에게 문의해 주세요."
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
msgid "Join the Discord server"
msgstr "디스코드 서버 입장"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
msgid "Leave- and rejoin the Discord Server (Reset)"
msgstr "디스코드 서버를 나가고 다시 입장하기 (리셋)"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
msgid "Leave the Discord server"
msgstr "디스코드 서버 나가기"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
msgid "Link Discord Server" msgid "Link Discord Server"
msgstr "디스코드 서버 링크" msgstr "디스코드 서버 링크"
#: allianceauth/services/modules/discord/views.py:26 #: allianceauth/services/modules/discord/views.py:30
msgid "Deactivated Discord account." msgid "Deactivated Discord account."
msgstr "디스코드 계정 해제 완료" msgstr "디스코드 계정 해제 완료"
#: allianceauth/services/modules/discord/views.py:29 #: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:41 #: allianceauth/services/modules/discord/views.py:59
#: allianceauth/services/modules/discord/views.py:65
msgid "An error occurred while processing your Discord account." msgid "An error occurred while processing your Discord account."
msgstr "디스코드 계정 처리 중 오류가 발생했습니다." msgstr "디스코드 계정 처리 중 오류가 발생했습니다."
#: allianceauth/services/modules/discord/views.py:62 #: allianceauth/services/modules/discord/views.py:102
msgid "Activated Discord account." msgid "Your Discord account has been successfully activated."
msgstr "디스코드 계정 활성화 완료" msgstr "디스코드 계정과 성공적으로 연동됐습니다."
#: allianceauth/services/modules/discord/views.py:108
msgid ""
"An error occurred while trying to activate your Discord account. Please try "
"again."
msgstr "디스코드 계정 연동 중 오류가 발생했습니다. 다시 시도해 주세요."
#: allianceauth/services/modules/discourse/views.py:37 #: allianceauth/services/modules/discourse/views.py:37
msgid "You are not authorized to access Discourse." msgid "You are not authorized to access Discourse."
@@ -1565,7 +1603,7 @@ msgstr "서드파티"
msgid "Domain" msgid "Domain"
msgstr "도메인" msgstr "도메인"
#: allianceauth/srp/auth_hooks.py:9 #: allianceauth/srp/auth_hooks.py:12
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "SRP" msgstr "SRP"
@@ -1579,7 +1617,7 @@ msgstr "플릿 시간"
msgid "Fleet Doctrine" msgid "Fleet Doctrine"
msgstr "플릿 독트린" msgstr "플릿 독트린"
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89 #: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
msgid "Additional Info" msgid "Additional Info"
msgstr "추가 기재 사항" msgstr "추가 기재 사항"
@@ -1608,63 +1646,63 @@ msgstr "SRP 보상 플릿 생성"
msgid "Give this link to the line members" msgid "Give this link to the line members"
msgstr "이 링크를 직계 멤버들에게 전달" msgstr "이 링크를 직계 멤버들에게 전달"
#: allianceauth/srp/templates/srp/data.html:48 #: allianceauth/srp/templates/srp/data.html:49
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "SRP 보상 플릿 데이터" msgstr "SRP 보상 플릿 데이터"
#: allianceauth/srp/templates/srp/data.html:53 #: allianceauth/srp/templates/srp/data.html:54
msgid "Mark Incomplete" msgid "Mark Incomplete"
msgstr "표시 미완료" msgstr "표시 미완료"
#: allianceauth/srp/templates/srp/data.html:57 #: allianceauth/srp/templates/srp/data.html:58
msgid "Mark Completed" msgid "Mark Completed"
msgstr "표시 완료" msgstr "표시 완료"
#: allianceauth/srp/templates/srp/data.html:69 #: allianceauth/srp/templates/srp/data.html:70
#: allianceauth/srp/templates/srp/data.html:145 #: allianceauth/srp/templates/srp/data.html:156
msgid "Total Losses:" msgid "Total Losses:"
msgstr "전체 손실:" msgstr "전체 손실:"
#: allianceauth/srp/templates/srp/data.html:70 #: allianceauth/srp/templates/srp/data.html:71
#: allianceauth/srp/templates/srp/data.html:146 #: allianceauth/srp/templates/srp/data.html:157
#: allianceauth/srp/templates/srp/management.html:30 #: allianceauth/srp/templates/srp/management.html:30
msgid "Total ISK Cost:" msgid "Total ISK Cost:"
msgstr "전체 ISK 비용:" msgstr "전체 ISK 비용:"
#: allianceauth/srp/templates/srp/data.html:78 #: allianceauth/srp/templates/srp/data.html:79
#: allianceauth/srp/templates/srp/data.html:154 #: allianceauth/srp/templates/srp/data.html:165
msgid "Are you sure you want to delete SRP requests?" msgid "Are you sure you want to delete SRP requests?"
msgstr "SRP 보상 요청을 삭제하시겠습니까?" msgstr "SRP 보상 요청을 삭제하시겠습니까?"
#: allianceauth/srp/templates/srp/data.html:87 #: allianceauth/srp/templates/srp/data.html:88
msgid "Pilot Name" msgid "Pilot Name"
msgstr "파일럿 이름" msgstr "파일럿 이름"
#: allianceauth/srp/templates/srp/data.html:88 #: allianceauth/srp/templates/srp/data.html:89
msgid "Killboard Link" msgid "Killboard Link"
msgstr "킬보드 링크" msgstr "킬보드 링크"
#: allianceauth/srp/templates/srp/data.html:90 #: allianceauth/srp/templates/srp/data.html:91
msgid "Ship Type" msgid "Ship Type"
msgstr "함선 종류" msgstr "함선 종류"
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:92
msgid "Killboard Loss Amt" msgid "Killboard Loss Amt"
msgstr "킬보드상 손실 금액" msgstr "킬보드상 손실 금액"
#: allianceauth/srp/templates/srp/data.html:92 #: allianceauth/srp/templates/srp/data.html:93
msgid "SRP ISK Cost" msgid "SRP ISK Cost"
msgstr "SRP 보상 비용" msgstr "SRP 보상 비용"
#: allianceauth/srp/templates/srp/data.html:93 #: allianceauth/srp/templates/srp/data.html:94
msgid "Click value to edit Enter to save & next ESC to cancel" msgid "Click value to edit Enter to save & next ESC to cancel"
msgstr "금액을 수정하려면 클릭, 저장을 하고 다음으로 가려면 엔터, 취소를 하려면 ESC를 누르세요. " msgstr "금액을 수정하려면 클릭, 저장을 하고 다음으로 가려면 엔터, 취소를 하려면 ESC를 누르세요. "
#: allianceauth/srp/templates/srp/data.html:96 #: allianceauth/srp/templates/srp/data.html:97
msgid "Post Time" msgid "Post Time"
msgstr "작성 시간" msgstr "작성 시간"
#: allianceauth/srp/templates/srp/data.html:163 #: allianceauth/srp/templates/srp/data.html:174
msgid "No SRP requests for this fleet." msgid "No SRP requests for this fleet."
msgstr "이 플릿에는 SRP 보상 요청이 없습니다." msgstr "이 플릿에는 SRP 보상 요청이 없습니다."
@@ -1856,32 +1894,30 @@ msgid "Current"
msgstr "현재" msgstr "현재"
#: allianceauth/templates/allianceauth/admin-status/overview.html:40 #: allianceauth/templates/allianceauth/admin-status/overview.html:40
msgid "Latest Major" msgid "Latest Stable"
msgstr "최근 주요 사항" msgstr "최신 안정화 버전"
#: allianceauth/templates/allianceauth/admin-status/overview.html:46 #: allianceauth/templates/allianceauth/admin-status/overview.html:46
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
msgid "Update available" msgid "Update available"
msgstr "업데이트 가능" msgstr "업데이트 가능"
#: allianceauth/templates/allianceauth/admin-status/overview.html:50 #: allianceauth/templates/allianceauth/admin-status/overview.html:51
msgid "Latest Minor" msgid "Latest Pre-Release"
msgstr "최근 기타 사항" msgstr "최신 사전 출시 버전"
#: allianceauth/templates/allianceauth/admin-status/overview.html:60 #: allianceauth/templates/allianceauth/admin-status/overview.html:57
msgid "Latest Patch" msgid "Pre-Release available"
msgstr "최근 패치" msgstr "사전 출시 사용 가능"
#: allianceauth/templates/allianceauth/admin-status/overview.html:73 #: allianceauth/templates/allianceauth/admin-status/overview.html:65
msgid "Task Queue" msgid "Task Queue"
msgstr "대기 중인 할 일" msgstr "대기 중인 할 일"
#: allianceauth/templates/allianceauth/admin-status/overview.html:90 #: allianceauth/templates/allianceauth/admin-status/overview.html:82
msgid "Error retrieving task queue length" msgid "Error retrieving task queue length"
msgstr "대기 중인 할 일 목록 회수 에러" msgstr "대기 중인 할 일 목록 회수 에러"
#: allianceauth/templates/allianceauth/admin-status/overview.html:92 #: allianceauth/templates/allianceauth/admin-status/overview.html:84
#, python-format #, python-format
msgid "%(tasks)s task" msgid "%(tasks)s task"
msgid_plural "%(tasks)s tasks" msgid_plural "%(tasks)s tasks"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-08 00:57+0000\n" "POT-Creation-Date: 2020-10-11 03:43+0000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Alexander Gess <de.alex.gess@gmail.com>, 2020\n" "Last-Translator: Alexander Gess <de.alex.gess@gmail.com>, 2020\n"
"Language-Team: Russian (https://www.transifex.com/alliance-auth/teams/107430/ru/)\n" "Language-Team: Russian (https://www.transifex.com/alliance-auth/teams/107430/ru/)\n"
@@ -25,59 +25,60 @@ msgstr ""
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "Необходимо указать основного персонажа. Добавим?" msgstr "Необходимо указать основного персонажа. Добавим?"
#: allianceauth/authentication/forms.py:6 #: allianceauth/authentication/forms.py:5
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
#: allianceauth/authentication/models.py:76 #: allianceauth/authentication/models.py:78
msgid "State Changed"
msgstr "Состояние заменено. "
#: allianceauth/authentication/models.py:77
#, python-format #, python-format
msgid "Your user state has been changed to %(state)s" msgid "State changed to: %s"
msgstr "Статус вашего пользователя сменен на %(state)s" msgstr "Статус изменен: %s"
#: allianceauth/authentication/models.py:79
#, python-format
msgid "Your user's state is now: %(state)s"
msgstr "Статус пилота: %(state)s"
#: allianceauth/authentication/templates/authentication/dashboard.html:5 #: allianceauth/authentication/templates/authentication/dashboard.html:5
#: allianceauth/authentication/templates/authentication/dashboard.html:8 #: allianceauth/authentication/templates/authentication/dashboard.html:8
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:11
msgid "Dashboard" msgid "Dashboard"
msgstr "Панель показателей" msgstr "Панель показателей"
#: allianceauth/authentication/templates/authentication/dashboard.html:17 #: allianceauth/authentication/templates/authentication/dashboard.html:18
#: allianceauth/corputils/templates/corputils/corpstats.html:116 #, python-format
#: allianceauth/corputils/templates/corputils/search.html:16 msgid ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22 "\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:83 " Main Character (State: %(state)s)\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:128 " "
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25 msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/view.html:32 "\n"
msgid "Main Character" " Основной персонаж (статус: %(state)s)\n"
msgstr "Основной персонаж" " "
#: allianceauth/authentication/templates/authentication/dashboard.html:77 #: allianceauth/authentication/templates/authentication/dashboard.html:81
msgid "No main character set." msgid "No main character set."
msgstr "Основной персонаж не установлен." msgstr "Основной персонаж не установлен."
#: allianceauth/authentication/templates/authentication/dashboard.html:84 #: allianceauth/authentication/templates/authentication/dashboard.html:88
msgid "Add Character" msgid "Add Character"
msgstr "Добавить Персонажа" msgstr "Добавить Персонажа"
#: allianceauth/authentication/templates/authentication/dashboard.html:88 #: allianceauth/authentication/templates/authentication/dashboard.html:92
msgid "Change Main" msgid "Change Main"
msgstr "Сменить основного персонажа" msgstr "Сменить основного персонажа"
#: allianceauth/authentication/templates/authentication/dashboard.html:97 #: allianceauth/authentication/templates/authentication/dashboard.html:101
msgid "Group Memberships" msgid "Group Memberships"
msgstr "Групповое участие" msgstr "Групповое участие"
#: allianceauth/authentication/templates/authentication/dashboard.html:117 #: allianceauth/authentication/templates/authentication/dashboard.html:121
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:41 #: allianceauth/hrapplications/templates/hrapplications/view.html:41
msgid "Characters" msgid "Characters"
msgstr "Персонажи" msgstr "Персонажи"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:129
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
@@ -86,13 +87,13 @@ msgstr "Персонажи"
msgid "Name" msgid "Name"
msgstr "Имя" msgstr "Имя"
#: allianceauth/authentication/templates/authentication/dashboard.html:126 #: allianceauth/authentication/templates/authentication/dashboard.html:130
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:46 #: allianceauth/hrapplications/templates/hrapplications/view.html:46
msgid "Corp" msgid "Corp"
msgstr "Корпорация" msgstr "Корпорация"
#: allianceauth/authentication/templates/authentication/dashboard.html:127 #: allianceauth/authentication/templates/authentication/dashboard.html:131
#: allianceauth/corputils/templates/corputils/corpstats.html:77 #: allianceauth/corputils/templates/corputils/corpstats.html:77
#: allianceauth/hrapplications/templates/hrapplications/view.html:47 #: allianceauth/hrapplications/templates/hrapplications/view.html:47
msgid "Alliance" msgid "Alliance"
@@ -141,6 +142,7 @@ msgid ""
"Cannot change main character to %(char)s: character owned by a different " "Cannot change main character to %(char)s: character owned by a different "
"account." "account."
msgstr "" msgstr ""
"Нельзя сменить основного персонажа на %(char)s: похоже, что Владелец не Вы. "
#: allianceauth/authentication/views.py:80 #: allianceauth/authentication/views.py:80
#, python-format #, python-format
@@ -161,21 +163,21 @@ msgstr "Персонаж %(name)s уже добавлен."
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "Невозможно авторизировать этого персонажа. " msgstr "Невозможно авторизировать этого персонажа. "
#: allianceauth/authentication/views.py:148 #: allianceauth/authentication/views.py:146
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "Регистрационный токен просрочен." msgstr "Регистрационный токен просрочен."
#: allianceauth/authentication/views.py:200 #: allianceauth/authentication/views.py:201
msgid "" msgid ""
"Sent confirmation email. Please follow the link to confirm your email " "Sent confirmation email. Please follow the link to confirm your email "
"address." "address."
msgstr "Отправить подтверждающее письмо. Пожалуйста, подтвердите почту. " msgstr "Отправить подтверждающее письмо. Пожалуйста, подтвердите почту. "
#: allianceauth/authentication/views.py:205 #: allianceauth/authentication/views.py:206
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "Подтвердите Ваш email адрес. Зайти для подтверждения. " msgstr "Подтвердите Ваш email адрес. Зайти для подтверждения. "
#: allianceauth/authentication/views.py:210 #: allianceauth/authentication/views.py:211
msgid "Registraion of new accounts it not allowed at this time." msgid "Registraion of new accounts it not allowed at this time."
msgstr "Регистрация нового аккаунта сейчас невозможна." msgstr "Регистрация нового аккаунта сейчас невозможна."
@@ -226,8 +228,8 @@ msgstr "Последнее обновление: "
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
msgid "Character" msgid "Character"
msgstr "Персонаж" msgstr "Персонаж"
@@ -249,6 +251,16 @@ msgstr "Корпорация"
msgid "Killboard" msgid "Killboard"
msgstr "zKillBoard" msgstr "zKillBoard"
#: allianceauth/corputils/templates/corputils/corpstats.html:116
#: allianceauth/corputils/templates/corputils/search.html:16
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "Основной персонаж"
#: allianceauth/corputils/templates/corputils/corpstats.html:117 #: allianceauth/corputils/templates/corputils/corpstats.html:117
#: allianceauth/corputils/templates/corputils/search.html:17 #: allianceauth/corputils/templates/corputils/search.html:17
msgid "Main Corporation" msgid "Main Corporation"
@@ -536,6 +548,11 @@ msgstr "Флотовое участие зарегистрированно."
msgid "FAT link has expired." msgid "FAT link has expired."
msgstr "ФлАк ссылка устарела" msgstr "ФлАк ссылка устарела"
#: allianceauth/groupmanagement/auth_hooks.py:16
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
msgid "Group Management"
msgstr "Управление Группой"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
msgid "Audit Log" msgid "Audit Log"
@@ -588,8 +605,8 @@ msgid "Portrait"
msgstr "Портрет" msgstr "Портрет"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
msgid "Organization" msgid "Organization"
msgstr "Корпорация" msgstr "Корпорация"
@@ -608,7 +625,7 @@ msgstr "Участники группы"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:15 #: allianceauth/templates/allianceauth/side-menu.html:16
msgid "Groups" msgid "Groups"
msgstr "Группы" msgstr "Группы"
@@ -622,7 +639,7 @@ msgstr "Описание"
#: allianceauth/hrapplications/templates/hrapplications/management.html:85 #: allianceauth/hrapplications/templates/hrapplications/management.html:85
#: allianceauth/hrapplications/templates/hrapplications/management.html:130 #: allianceauth/hrapplications/templates/hrapplications/management.html:130
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/srp/templates/srp/data.html:97 #: allianceauth/srp/templates/srp/data.html:98
msgid "Status" msgid "Status"
msgstr "Статус" msgstr "Статус"
@@ -652,8 +669,8 @@ msgid "Audit Members"
msgstr "Проверить участников" msgstr "Проверить участников"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
msgid "Copy Direrct Join Link" msgid "Copy Direct Join Link"
msgstr "" msgstr "Скопировать ссылку подключения"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
msgid "No groups to list." msgid "No groups to list."
@@ -684,37 +701,37 @@ msgstr "Нет доступных групп."
msgid "Groups Management" msgid "Groups Management"
msgstr "Управление Группами" msgstr "Управление Группами"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
msgid "Join Requests" msgid "Join Requests"
msgstr "Запрос на присоединение" msgstr "Запрос на присоединение"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
msgid "Leave Requests" msgid "Leave Requests"
msgstr "Запрос на Выход" msgstr "Запрос на Выход"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "Группа" msgstr "Группа"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
msgid "Accept" msgid "Accept"
msgstr "Принять" msgstr "Принять"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
#: allianceauth/hrapplications/templates/hrapplications/view.html:85 #: allianceauth/hrapplications/templates/hrapplications/view.html:85
msgid "Reject" msgid "Reject"
msgstr "Сбросить" msgstr "Сбросить"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
msgid "No group add requests." msgid "No group add requests."
msgstr "Нет групповых запросов на вступление" msgstr "Нет групповых запросов на вступление"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
msgid "No group leave requests." msgid "No group leave requests."
msgstr "Нет групповых запросов на выход" msgstr "Нет групповых запросов на выход"
@@ -722,11 +739,6 @@ msgstr "Нет групповых запросов на выход"
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "Проложить маршрут" msgstr "Проложить маршрут"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
#: allianceauth/templates/allianceauth/side-menu.html:23
msgid "Group Management"
msgstr "Управление Группой"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
msgid "Group Requests" msgid "Group Requests"
msgstr "Групповой запрос" msgstr "Групповой запрос"
@@ -735,26 +747,26 @@ msgstr "Групповой запрос"
msgid "Group Membership" msgid "Group Membership"
msgstr "Групповое участие" msgstr "Групповое участие"
#: allianceauth/groupmanagement/views.py:166 #: allianceauth/groupmanagement/views.py:162
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "Пользователь %(user)s исключен из %(group)s." msgstr "Пользователь %(user)s исключен из %(group)s."
#: allianceauth/groupmanagement/views.py:168 #: allianceauth/groupmanagement/views.py:164
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "Пользователь не существует в этой группе." msgstr "Пользователь не существует в этой группе."
#: allianceauth/groupmanagement/views.py:171 #: allianceauth/groupmanagement/views.py:167
msgid "Group does not exist" msgid "Group does not exist"
msgstr "Группа не существует." msgstr "Группа не существует."
#: allianceauth/groupmanagement/views.py:198 #: allianceauth/groupmanagement/views.py:194
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "Запрос от %(mainchar)sв %(group)s принят." msgstr "Запрос от %(mainchar)sв %(group)s принят."
#: allianceauth/groupmanagement/views.py:205 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:238 #: allianceauth/groupmanagement/views.py:234
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
@@ -763,78 +775,80 @@ msgstr ""
"Персонаж %(mainchar)s не может быть добавлен %(group)s, из-за непредвиденной" "Персонаж %(mainchar)s не может быть добавлен %(group)s, из-за непредвиденной"
" ошибки. " " ошибки. "
#: allianceauth/groupmanagement/views.py:231 #: allianceauth/groupmanagement/views.py:227
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "%(mainchar)s исключен из %(group)s." msgstr "%(mainchar)s исключен из %(group)s."
#: allianceauth/groupmanagement/views.py:267 #: allianceauth/groupmanagement/views.py:263
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "Утвержден выход %(mainchar)s из %(group)s. " msgstr "Утвержден выход %(mainchar)s из %(group)s. "
#: allianceauth/groupmanagement/views.py:273 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:307 #: allianceauth/groupmanagement/views.py:303
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "" msgstr ""
"Возникла ошибка во время обработки %(mainchar)s на выход из группы "
"%(group)s. Повторите позже."
#: allianceauth/groupmanagement/views.py:300 #: allianceauth/groupmanagement/views.py:296
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "Прошение об исключении %(mainchar)s из %(group)s отклонено. " msgstr "Прошение об исключении %(mainchar)s из %(group)s отклонено. "
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:342
#: allianceauth/groupmanagement/views.py:358 #: allianceauth/groupmanagement/views.py:354
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "Вы не можете вступить" msgstr "Вы не можете вступить"
#: allianceauth/groupmanagement/views.py:352 #: allianceauth/groupmanagement/views.py:348
msgid "You are already a member of that group." msgid "You are already a member of that group."
msgstr "" msgstr "Вы уже участник этой группы."
#: allianceauth/groupmanagement/views.py:367 #: allianceauth/groupmanagement/views.py:363
msgid "You already have a pending application for that group." msgid "You already have a pending application for that group."
msgstr "" msgstr "Вы уже подали заявку на вступление этой группы."
#: allianceauth/groupmanagement/views.py:370 #: allianceauth/groupmanagement/views.py:366
#: allianceauth/groupmanagement/views.py:408 #: allianceauth/groupmanagement/views.py:404
#: allianceauth/hrapplications/templates/hrapplications/management.html:37 #: allianceauth/hrapplications/templates/hrapplications/management.html:37
#: allianceauth/hrapplications/templates/hrapplications/management.html:72 #: allianceauth/hrapplications/templates/hrapplications/management.html:72
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:144 #: allianceauth/hrapplications/templates/hrapplications/management.html:144
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
#: allianceauth/hrapplications/templates/hrapplications/view.html:20 #: allianceauth/hrapplications/templates/hrapplications/view.html:20
#: allianceauth/srp/templates/srp/data.html:125 #: allianceauth/srp/templates/srp/data.html:134
#: allianceauth/srp/templates/srp/management.html:81 #: allianceauth/srp/templates/srp/management.html:81
msgid "Pending" msgid "Pending"
msgstr "Ожидание" msgstr "Ожидание"
#: allianceauth/groupmanagement/views.py:376 #: allianceauth/groupmanagement/views.py:372
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "Вступить в группу %(group)s." msgstr "Вступить в группу %(group)s."
#: allianceauth/groupmanagement/views.py:387 #: allianceauth/groupmanagement/views.py:383
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "Вы не можете покинуть эту группу" msgstr "Вы не можете покинуть эту группу"
#: allianceauth/groupmanagement/views.py:392 #: allianceauth/groupmanagement/views.py:388
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "Вы не участник группыы" msgstr "Вы не участник группыы"
#: allianceauth/groupmanagement/views.py:401 #: allianceauth/groupmanagement/views.py:397
msgid "You already have a pending leave request for that group." msgid "You already have a pending leave request for that group."
msgstr "" msgstr "Ваш запрос находится на рассмотрении"
#: allianceauth/groupmanagement/views.py:414 #: allianceauth/groupmanagement/views.py:410
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "Запрос на выход из группы %(group)s." msgstr "Запрос на выход из группы %(group)s."
#: allianceauth/hrapplications/auth_hooks.py:10 #: allianceauth/hrapplications/auth_hooks.py:13
msgid "Applications" msgid "Applications"
msgstr "Запросы" msgstr "Запросы"
@@ -891,7 +905,7 @@ msgstr "Пользователь"
#: allianceauth/hrapplications/templates/hrapplications/management.html:131 #: allianceauth/hrapplications/templates/hrapplications/management.html:131
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
#: allianceauth/hrapplications/templates/hrapplications/view.html:75 #: allianceauth/hrapplications/templates/hrapplications/view.html:75
#: allianceauth/srp/templates/srp/data.html:99 #: allianceauth/srp/templates/srp/data.html:100
#: allianceauth/srp/templates/srp/management.html:46 #: allianceauth/srp/templates/srp/management.html:46
msgid "Actions" msgid "Actions"
msgstr "Действия" msgstr "Действия"
@@ -901,7 +915,7 @@ msgstr "Действия"
#: allianceauth/hrapplications/templates/hrapplications/management.html:147 #: allianceauth/hrapplications/templates/hrapplications/management.html:147
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
#: allianceauth/hrapplications/templates/hrapplications/view.html:16 #: allianceauth/hrapplications/templates/hrapplications/view.html:16
#: allianceauth/srp/templates/srp/data.html:117 #: allianceauth/srp/templates/srp/data.html:126
msgid "Approved" msgid "Approved"
msgstr "Проверено" msgstr "Проверено"
@@ -909,7 +923,7 @@ msgstr "Проверено"
#: allianceauth/hrapplications/templates/hrapplications/management.html:104 #: allianceauth/hrapplications/templates/hrapplications/management.html:104
#: allianceauth/hrapplications/templates/hrapplications/management.html:149 #: allianceauth/hrapplications/templates/hrapplications/management.html:149
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
#: allianceauth/srp/templates/srp/data.html:121 #: allianceauth/srp/templates/srp/data.html:130
msgid "Rejected" msgid "Rejected"
msgstr "Отменено " msgstr "Отменено "
@@ -1222,15 +1236,15 @@ msgstr "Состояния"
#: allianceauth/services/abstract.py:72 #: allianceauth/services/abstract.py:72
msgid "That service account already exists" msgid "That service account already exists"
msgstr "" msgstr "Этот сервис уже активирован"
#: allianceauth/services/abstract.py:104 #: allianceauth/services/abstract.py:104
msgid "Successfully set your {} password" msgid "Successfully set your {} password"
msgstr "" msgstr "{} Пароль успешно обновлен."
#: allianceauth/services/auth_hooks.py:11 #: allianceauth/services/auth_hooks.py:11
msgid "Services" msgid "Services"
msgstr "" msgstr "Сервисные услуги"
#: allianceauth/services/forms.py:6 #: allianceauth/services/forms.py:6
msgid "Name of Fleet:" msgid "Name of Fleet:"
@@ -1292,37 +1306,74 @@ msgstr "Пароль"
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "Пароль должен быть не менее 8 символов." msgstr "Пароль должен быть не менее 8 символов."
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23 #: allianceauth/services/modules/discord/models.py:225
msgid "Discord Account Disabled"
msgstr "Discord персонаж отключен"
#: allianceauth/services/modules/discord/models.py:227
msgid ""
"Your Discord account was disabeled automatically by Auth. If you think this "
"was a mistake, please contact an admin."
msgstr ""
"Ваш доступ на сервер Discord был отменен. Если Вы считаете что по ошибке, "
"пожалуйста, свяжитесь с СЕО."
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
msgid "Join the Discord server"
msgstr "Подключиться к серверу Discord"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
msgid "Leave- and rejoin the Discord Server (Reset)"
msgstr "Переподключиться к серверу Discord. "
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
msgid "Leave the Discord server"
msgstr "Покинуть Discord сервер"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
msgid "Link Discord Server" msgid "Link Discord Server"
msgstr "Ссылка на сервер Discord" msgstr "Ссылка на сервер Discord"
#: allianceauth/services/modules/discord/views.py:26 #: allianceauth/services/modules/discord/views.py:30
msgid "Deactivated Discord account." msgid "Deactivated Discord account."
msgstr "" msgstr "Отменить доступ на Discord сервер."
#: allianceauth/services/modules/discord/views.py:29 #: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:41 #: allianceauth/services/modules/discord/views.py:59
#: allianceauth/services/modules/discord/views.py:65
msgid "An error occurred while processing your Discord account." msgid "An error occurred while processing your Discord account."
msgstr "" msgstr ""
"Во время обработки Discord аккаунта возникла ошибка. Попробуйте чуточку "
"позднее. "
#: allianceauth/services/modules/discord/views.py:62 #: allianceauth/services/modules/discord/views.py:102
msgid "Activated Discord account." msgid "Your Discord account has been successfully activated."
msgstr "Доступ на сервер Discord успешно получен."
#: allianceauth/services/modules/discord/views.py:108
msgid ""
"An error occurred while trying to activate your Discord account. Please try "
"again."
msgstr "" msgstr ""
"Во время активации Discord аккаунта возникла ошибка. Попробуйте чуточку "
"позднее. "
#: allianceauth/services/modules/discourse/views.py:37 #: allianceauth/services/modules/discourse/views.py:37
msgid "You are not authorized to access Discourse." msgid "You are not authorized to access Discourse."
msgstr "" msgstr "Вы не авторизованы в Discourse."
#: allianceauth/services/modules/discourse/views.py:42 #: allianceauth/services/modules/discourse/views.py:42
msgid "You must have a main character set to access Discourse." msgid "You must have a main character set to access Discourse."
msgstr "" msgstr ""
"Для авторизации Discourse, необходимо получить авторизацию Вашим основным "
"аккаунтом."
#: allianceauth/services/modules/discourse/views.py:52 #: allianceauth/services/modules/discourse/views.py:52
msgid "" msgid ""
"No SSO payload or signature. Please contact support if this problem " "No SSO payload or signature. Please contact support if this problem "
"persists." "persists."
msgstr "" msgstr ""
"Отсуствует связь SSO. Если ошибка повторяется - свяжитесь с тех. поддержкой."
" "
#: allianceauth/services/modules/discourse/views.py:62 #: allianceauth/services/modules/discourse/views.py:62
#: allianceauth/services/modules/discourse/views.py:70 #: allianceauth/services/modules/discourse/views.py:70
@@ -1354,7 +1405,7 @@ msgstr ""
#: allianceauth/services/modules/openfire/auth_hooks.py:26 #: allianceauth/services/modules/openfire/auth_hooks.py:26
msgid "Jabber" msgid "Jabber"
msgstr "" msgstr "Jabber"
#: allianceauth/services/modules/openfire/auth_hooks.py:78 #: allianceauth/services/modules/openfire/auth_hooks.py:78
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:6 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:6
@@ -1380,50 +1431,50 @@ msgstr "Бродкаст"
#: allianceauth/services/modules/openfire/views.py:35 #: allianceauth/services/modules/openfire/views.py:35
msgid "Activated jabber account." msgid "Activated jabber account."
msgstr "" msgstr "Активировать доступ в jabber."
#: allianceauth/services/modules/openfire/views.py:44 #: allianceauth/services/modules/openfire/views.py:44
#: allianceauth/services/modules/openfire/views.py:57 #: allianceauth/services/modules/openfire/views.py:57
#: allianceauth/services/modules/openfire/views.py:78 #: allianceauth/services/modules/openfire/views.py:78
#: allianceauth/services/modules/openfire/views.py:151 #: allianceauth/services/modules/openfire/views.py:151
msgid "An error occurred while processing your jabber account." msgid "An error occurred while processing your jabber account."
msgstr "" msgstr "Возникла ошибка во время активации jabber'а ."
#: allianceauth/services/modules/openfire/views.py:70 #: allianceauth/services/modules/openfire/views.py:70
msgid "Reset jabber password." msgid "Reset jabber password."
msgstr "" msgstr "Сбросить jabber пароль."
#: allianceauth/services/modules/openfire/views.py:119 #: allianceauth/services/modules/openfire/views.py:119
#, python-format #, python-format
msgid "Sent jabber broadcast to %s" msgid "Sent jabber broadcast to %s"
msgstr "" msgstr "Отправить Бродкаст %s"
#: allianceauth/services/modules/openfire/views.py:148 #: allianceauth/services/modules/openfire/views.py:148
msgid "Set jabber password." msgid "Set jabber password."
msgstr "" msgstr "Установить jabber пароль."
#: allianceauth/services/modules/phpbb3/views.py:34 #: allianceauth/services/modules/phpbb3/views.py:34
msgid "Activated forum account." msgid "Activated forum account."
msgstr "" msgstr "Допустить на Форум."
#: allianceauth/services/modules/phpbb3/views.py:43 #: allianceauth/services/modules/phpbb3/views.py:43
#: allianceauth/services/modules/phpbb3/views.py:57 #: allianceauth/services/modules/phpbb3/views.py:57
#: allianceauth/services/modules/phpbb3/views.py:80 #: allianceauth/services/modules/phpbb3/views.py:80
#: allianceauth/services/modules/phpbb3/views.py:103 #: allianceauth/services/modules/phpbb3/views.py:103
msgid "An error occurred while processing your forum account." msgid "An error occurred while processing your forum account."
msgstr "" msgstr "Во время обработки Форумного аккаунта, возникла ошибка."
#: allianceauth/services/modules/phpbb3/views.py:54 #: allianceauth/services/modules/phpbb3/views.py:54
msgid "Deactivated forum account." msgid "Deactivated forum account."
msgstr "" msgstr "Отменить доступ на Форум. "
#: allianceauth/services/modules/phpbb3/views.py:71 #: allianceauth/services/modules/phpbb3/views.py:71
msgid "Reset forum password." msgid "Reset forum password."
msgstr "" msgstr "Сбросить пароль на Форум."
#: allianceauth/services/modules/phpbb3/views.py:100 #: allianceauth/services/modules/phpbb3/views.py:100
msgid "Set forum password." msgid "Set forum password."
msgstr "" msgstr "Установить пароль на Форум."
#: allianceauth/services/modules/smf/views.py:34 #: allianceauth/services/modules/smf/views.py:34
msgid "Activated SMF account." msgid "Activated SMF account."
@@ -1473,21 +1524,21 @@ msgstr "Продолжить"
#: allianceauth/services/modules/teamspeak3/views.py:34 #: allianceauth/services/modules/teamspeak3/views.py:34
msgid "Activated TeamSpeak3 account." msgid "Activated TeamSpeak3 account."
msgstr "" msgstr "Активировать аккаунт TeamSpeak3."
#: allianceauth/services/modules/teamspeak3/views.py:37 #: allianceauth/services/modules/teamspeak3/views.py:37
#: allianceauth/services/modules/teamspeak3/views.py:74 #: allianceauth/services/modules/teamspeak3/views.py:74
#: allianceauth/services/modules/teamspeak3/views.py:100 #: allianceauth/services/modules/teamspeak3/views.py:100
msgid "An error occurred while processing your TeamSpeak3 account." msgid "An error occurred while processing your TeamSpeak3 account."
msgstr "" msgstr "Во время активации TeamSpeak3 возникла ошибка, попробуйте позже."
#: allianceauth/services/modules/teamspeak3/views.py:71 #: allianceauth/services/modules/teamspeak3/views.py:71
msgid "Deactivated TeamSpeak3 account." msgid "Deactivated TeamSpeak3 account."
msgstr "" msgstr "Отключить TeamSpeak3 аккаунт."
#: allianceauth/services/modules/teamspeak3/views.py:97 #: allianceauth/services/modules/teamspeak3/views.py:97
msgid "Reset TeamSpeak3 permission key." msgid "Reset TeamSpeak3 permission key."
msgstr "" msgstr "Сбросить TeamSpeak3 ключ доступа."
#: allianceauth/services/modules/xenforo/views.py:30 #: allianceauth/services/modules/xenforo/views.py:30
msgid "Activated XenForo account." msgid "Activated XenForo account."
@@ -1572,7 +1623,7 @@ msgstr "Сервис"
msgid "Domain" msgid "Domain"
msgstr "Домен" msgstr "Домен"
#: allianceauth/srp/auth_hooks.py:9 #: allianceauth/srp/auth_hooks.py:12
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "Замена корабля" msgstr "Замена корабля"
@@ -1586,7 +1637,7 @@ msgstr "Флотовое время"
msgid "Fleet Doctrine" msgid "Fleet Doctrine"
msgstr "Флотовая Доктрина" msgstr "Флотовая Доктрина"
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89 #: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
msgid "Additional Info" msgid "Additional Info"
msgstr "Дополнительная информация" msgstr "Дополнительная информация"
@@ -1615,63 +1666,63 @@ msgstr "Создать SRP Флот"
msgid "Give this link to the line members" msgid "Give this link to the line members"
msgstr "Поделиться ссылкой с рядовыми участниками" msgstr "Поделиться ссылкой с рядовыми участниками"
#: allianceauth/srp/templates/srp/data.html:48 #: allianceauth/srp/templates/srp/data.html:49
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "SRP данные флота" msgstr "SRP данные флота"
#: allianceauth/srp/templates/srp/data.html:53 #: allianceauth/srp/templates/srp/data.html:54
msgid "Mark Incomplete" msgid "Mark Incomplete"
msgstr "Пометить незаконченным" msgstr "Пометить незаконченным"
#: allianceauth/srp/templates/srp/data.html:57 #: allianceauth/srp/templates/srp/data.html:58
msgid "Mark Completed" msgid "Mark Completed"
msgstr "Пометить законченным" msgstr "Пометить законченным"
#: allianceauth/srp/templates/srp/data.html:69 #: allianceauth/srp/templates/srp/data.html:70
#: allianceauth/srp/templates/srp/data.html:145 #: allianceauth/srp/templates/srp/data.html:156
msgid "Total Losses:" msgid "Total Losses:"
msgstr "Суммарные потери:" msgstr "Суммарные потери:"
#: allianceauth/srp/templates/srp/data.html:70 #: allianceauth/srp/templates/srp/data.html:71
#: allianceauth/srp/templates/srp/data.html:146 #: allianceauth/srp/templates/srp/data.html:157
#: allianceauth/srp/templates/srp/management.html:30 #: allianceauth/srp/templates/srp/management.html:30
msgid "Total ISK Cost:" msgid "Total ISK Cost:"
msgstr "Оценочная стоимость (ISK):" msgstr "Оценочная стоимость (ISK):"
#: allianceauth/srp/templates/srp/data.html:78 #: allianceauth/srp/templates/srp/data.html:79
#: allianceauth/srp/templates/srp/data.html:154 #: allianceauth/srp/templates/srp/data.html:165
msgid "Are you sure you want to delete SRP requests?" msgid "Are you sure you want to delete SRP requests?"
msgstr "Вы уверенны что хотите удалить запрос на SRP?" msgstr "Вы уверенны что хотите удалить запрос на SRP?"
#: allianceauth/srp/templates/srp/data.html:87 #: allianceauth/srp/templates/srp/data.html:88
msgid "Pilot Name" msgid "Pilot Name"
msgstr "Имя Пилота" msgstr "Имя Пилота"
#: allianceauth/srp/templates/srp/data.html:88 #: allianceauth/srp/templates/srp/data.html:89
msgid "Killboard Link" msgid "Killboard Link"
msgstr "zKillBoard ссылка" msgstr "zKillBoard ссылка"
#: allianceauth/srp/templates/srp/data.html:90 #: allianceauth/srp/templates/srp/data.html:91
msgid "Ship Type" msgid "Ship Type"
msgstr "Тип корабля" msgstr "Тип корабля"
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:92
msgid "Killboard Loss Amt" msgid "Killboard Loss Amt"
msgstr "потерь по zKillBoard на данный момент" msgstr "потерь по zKillBoard на данный момент"
#: allianceauth/srp/templates/srp/data.html:92 #: allianceauth/srp/templates/srp/data.html:93
msgid "SRP ISK Cost" msgid "SRP ISK Cost"
msgstr "SRP ISK Стоимость" msgstr "SRP ISK Стоимость"
#: allianceauth/srp/templates/srp/data.html:93 #: allianceauth/srp/templates/srp/data.html:94
msgid "Click value to edit Enter to save & next ESC to cancel" msgid "Click value to edit Enter to save & next ESC to cancel"
msgstr "Нажмите на значение для редактирования и ESC для отмены" msgstr "Нажмите на значение для редактирования и ESC для отмены"
#: allianceauth/srp/templates/srp/data.html:96 #: allianceauth/srp/templates/srp/data.html:97
msgid "Post Time" msgid "Post Time"
msgstr "Опубликованно" msgstr "Опубликованно"
#: allianceauth/srp/templates/srp/data.html:163 #: allianceauth/srp/templates/srp/data.html:174
msgid "No SRP requests for this fleet." msgid "No SRP requests for this fleet."
msgstr "SRP запросы отсутствуют" msgstr "SRP запросы отсутствуют"
@@ -1866,32 +1917,30 @@ msgid "Current"
msgstr "Текущий" msgstr "Текущий"
#: allianceauth/templates/allianceauth/admin-status/overview.html:40 #: allianceauth/templates/allianceauth/admin-status/overview.html:40
msgid "Latest Major" msgid "Latest Stable"
msgstr "Последняя версия" msgstr "Стабильная Версия"
#: allianceauth/templates/allianceauth/admin-status/overview.html:46 #: allianceauth/templates/allianceauth/admin-status/overview.html:46
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
msgid "Update available" msgid "Update available"
msgstr "Доступно обновление" msgstr "Доступно обновление"
#: allianceauth/templates/allianceauth/admin-status/overview.html:50 #: allianceauth/templates/allianceauth/admin-status/overview.html:51
msgid "Latest Minor" msgid "Latest Pre-Release"
msgstr "Последняя версия" msgstr "Предрелизная Версия"
#: allianceauth/templates/allianceauth/admin-status/overview.html:60 #: allianceauth/templates/allianceauth/admin-status/overview.html:57
msgid "Latest Patch" msgid "Pre-Release available"
msgstr "Последние исправления" msgstr "Предрелизная Версия"
#: allianceauth/templates/allianceauth/admin-status/overview.html:73 #: allianceauth/templates/allianceauth/admin-status/overview.html:65
msgid "Task Queue" msgid "Task Queue"
msgstr "Список задач" msgstr "Список задач"
#: allianceauth/templates/allianceauth/admin-status/overview.html:90 #: allianceauth/templates/allianceauth/admin-status/overview.html:82
msgid "Error retrieving task queue length" msgid "Error retrieving task queue length"
msgstr "Ошибка при получении списка задач. " msgstr "Ошибка при получении списка задач. "
#: allianceauth/templates/allianceauth/admin-status/overview.html:92 #: allianceauth/templates/allianceauth/admin-status/overview.html:84
#, python-format #, python-format
msgid "%(tasks)s task" msgid "%(tasks)s task"
msgid_plural "%(tasks)s tasks" msgid_plural "%(tasks)s tasks"

View File

@@ -4,17 +4,18 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Joel Falknau <ozirascal@gmail.com>, 2020
# Jesse . <sgeine@hotmail.com>, 2020 # Jesse . <sgeine@hotmail.com>, 2020
# Aaron BuBu <351793078@qq.com>, 2020
# Joel Falknau <ozirascal@gmail.com>, 2020
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-03-10 01:32+0000\n" "POT-Creation-Date: 2020-10-11 03:43+0000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n" "PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Jesse . <sgeine@hotmail.com>, 2020\n" "Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
"Language-Team: Chinese Simplified (https://www.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n" "Language-Team: Chinese Simplified (https://www.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -26,59 +27,57 @@ msgstr ""
msgid "A main character is required to perform that action. Add one below." msgid "A main character is required to perform that action. Add one below."
msgstr "只有主要角色才能执行这个操作。在下面添加一个" msgstr "只有主要角色才能执行这个操作。在下面添加一个"
#: allianceauth/authentication/forms.py:6 #: allianceauth/authentication/forms.py:5
msgid "Email" msgid "Email"
msgstr "电子邮箱" msgstr "电子邮箱"
#: allianceauth/authentication/models.py:76 #: allianceauth/authentication/models.py:78
msgid "State Changed"
msgstr "状态已经更改"
#: allianceauth/authentication/models.py:77
#, python-format #, python-format
msgid "Your user state has been changed to %(state)s" msgid "State changed to: %s"
msgstr "您的用户状态已经更改为%(state)s" msgstr ""
#: allianceauth/authentication/models.py:79
#, python-format
msgid "Your user's state is now: %(state)s"
msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:5 #: allianceauth/authentication/templates/authentication/dashboard.html:5
#: allianceauth/authentication/templates/authentication/dashboard.html:8 #: allianceauth/authentication/templates/authentication/dashboard.html:8
#: allianceauth/templates/allianceauth/side-menu.html:10 #: allianceauth/templates/allianceauth/side-menu.html:11
msgid "Dashboard" msgid "Dashboard"
msgstr "账户总览" msgstr "账户总览"
#: allianceauth/authentication/templates/authentication/dashboard.html:17 #: allianceauth/authentication/templates/authentication/dashboard.html:18
#: allianceauth/corputils/templates/corputils/corpstats.html:116 #, python-format
#: allianceauth/corputils/templates/corputils/search.html:16 msgid ""
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22 "\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:83 " Main Character (State: %(state)s)\n"
#: allianceauth/hrapplications/templates/hrapplications/management.html:128 " "
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25 msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "主要角色"
#: allianceauth/authentication/templates/authentication/dashboard.html:77 #: allianceauth/authentication/templates/authentication/dashboard.html:81
msgid "No main character set." msgid "No main character set."
msgstr "没有主要角色组" msgstr "没有主要角色组"
#: allianceauth/authentication/templates/authentication/dashboard.html:84 #: allianceauth/authentication/templates/authentication/dashboard.html:88
msgid "Add Character" msgid "Add Character"
msgstr "添加角色" msgstr "添加角色"
#: allianceauth/authentication/templates/authentication/dashboard.html:88 #: allianceauth/authentication/templates/authentication/dashboard.html:92
msgid "Change Main" msgid "Change Main"
msgstr "修改主要角色" msgstr "修改主要角色"
#: allianceauth/authentication/templates/authentication/dashboard.html:97 #: allianceauth/authentication/templates/authentication/dashboard.html:101
msgid "Group Memberships" msgid "Group Memberships"
msgstr "用户组成员" msgstr "用户组成员"
#: allianceauth/authentication/templates/authentication/dashboard.html:117 #: allianceauth/authentication/templates/authentication/dashboard.html:121
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:41 #: allianceauth/hrapplications/templates/hrapplications/view.html:41
msgid "Characters" msgid "Characters"
msgstr "角色" msgstr "角色"
#: allianceauth/authentication/templates/authentication/dashboard.html:125 #: allianceauth/authentication/templates/authentication/dashboard.html:129
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
@@ -87,13 +86,13 @@ msgstr "角色"
msgid "Name" msgid "Name"
msgstr "角色名" msgstr "角色名"
#: allianceauth/authentication/templates/authentication/dashboard.html:126 #: allianceauth/authentication/templates/authentication/dashboard.html:130
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
#: allianceauth/hrapplications/templates/hrapplications/view.html:46 #: allianceauth/hrapplications/templates/hrapplications/view.html:46
msgid "Corp" msgid "Corp"
msgstr "所在公司" msgstr "所在公司"
#: allianceauth/authentication/templates/authentication/dashboard.html:127 #: allianceauth/authentication/templates/authentication/dashboard.html:131
#: allianceauth/corputils/templates/corputils/corpstats.html:77 #: allianceauth/corputils/templates/corputils/corpstats.html:77
#: allianceauth/hrapplications/templates/hrapplications/view.html:47 #: allianceauth/hrapplications/templates/hrapplications/view.html:47
msgid "Alliance" msgid "Alliance"
@@ -134,40 +133,47 @@ msgstr "您的IT团队"
msgid "Submit" msgid "Submit"
msgstr "提交" msgstr "提交"
#: allianceauth/authentication/views.py:77 #: allianceauth/authentication/views.py:74
#, python-format
msgid ""
"Cannot change main character to %(char)s: character owned by a different "
"account."
msgstr "不能修改主角色为%(char)s这个角色被另一个账户所拥有"
#: allianceauth/authentication/views.py:80
#, python-format #, python-format
msgid "Changed main character to %(char)s" msgid "Changed main character to %(char)s"
msgstr "修改主要角色为%(char)s" msgstr "修改主要角色为%(char)s"
#: allianceauth/authentication/views.py:86 #: allianceauth/authentication/views.py:89
#, python-format #, python-format
msgid "Added %(name)s to your account." msgid "Added %(name)s to your account."
msgstr "添加%(name)s到您的账户" msgstr "添加%(name)s到您的账户"
#: allianceauth/authentication/views.py:88 #: allianceauth/authentication/views.py:91
#, python-format #, python-format
msgid "Failed to add %(name)s to your account: they already have an account." msgid "Failed to add %(name)s to your account: they already have an account."
msgstr "添加%(name)s到您的账户失败他们已经在一个账户中了" msgstr "添加%(name)s到您的账户失败他们已经在一个账户中了"
#: allianceauth/authentication/views.py:127 #: allianceauth/authentication/views.py:130
msgid "Unable to authenticate as the selected character." msgid "Unable to authenticate as the selected character."
msgstr "无法作为选定的角色进行身份验证" msgstr "无法作为选定的角色进行身份验证"
#: allianceauth/authentication/views.py:145 #: allianceauth/authentication/views.py:146
msgid "Registration token has expired." msgid "Registration token has expired."
msgstr "注册令牌过期。" msgstr "注册令牌过期。"
#: allianceauth/authentication/views.py:197 #: allianceauth/authentication/views.py:201
msgid "" msgid ""
"Sent confirmation email. Please follow the link to confirm your email " "Sent confirmation email. Please follow the link to confirm your email "
"address." "address."
msgstr "已经发送了确认邮件。请按照链接确定您的电邮地址" msgstr "已经发送了确认邮件。请按照链接确定您的电邮地址"
#: allianceauth/authentication/views.py:202 #: allianceauth/authentication/views.py:206
msgid "Confirmed your email address. Please login to continue." msgid "Confirmed your email address. Please login to continue."
msgstr "已确认您的电邮地址。请登录以继续" msgstr "已确认您的电邮地址。请登录以继续"
#: allianceauth/authentication/views.py:207 #: allianceauth/authentication/views.py:211
msgid "Registraion of new accounts it not allowed at this time." msgid "Registraion of new accounts it not allowed at this time."
msgstr "现在不允许注册新账户。" msgstr "现在不允许注册新账户。"
@@ -218,8 +224,8 @@ msgstr "最后一次更新"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28 #: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
msgid "Character" msgid "Character"
msgstr "角色" msgstr "角色"
@@ -241,6 +247,16 @@ msgstr "公司"
msgid "Killboard" msgid "Killboard"
msgstr "KB板" msgstr "KB板"
#: allianceauth/corputils/templates/corputils/corpstats.html:116
#: allianceauth/corputils/templates/corputils/search.html:16
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
msgid "Main Character"
msgstr "主要角色"
#: allianceauth/corputils/templates/corputils/corpstats.html:117 #: allianceauth/corputils/templates/corputils/corpstats.html:117
#: allianceauth/corputils/templates/corputils/search.html:17 #: allianceauth/corputils/templates/corputils/search.html:17
msgid "Main Corporation" msgid "Main Corporation"
@@ -522,11 +538,22 @@ msgstr "成功注册舰队PAP"
msgid "FAT link has expired." msgid "FAT link has expired."
msgstr "PAP链接已过期" msgstr "PAP链接已过期"
#: allianceauth/groupmanagement/auth_hooks.py:16
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
msgid "Group Management"
msgstr "用户组管理"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
msgid "Audit Log" msgid "Audit Log"
msgstr "审计日志" msgstr "审计日志"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:18
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:20
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
msgid "Back"
msgstr "返回"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25 #: allianceauth/groupmanagement/templates/groupmanagement/audit.html:25
msgid "Date/Time" msgid "Date/Time"
msgstr "日期/时间" msgstr "日期/时间"
@@ -568,8 +595,8 @@ msgid "Portrait"
msgstr "人物头像" msgstr "人物头像"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
msgid "Organization" msgid "Organization"
msgstr "组织" msgstr "组织"
@@ -586,6 +613,12 @@ msgstr "用户组里没人呀,你叫我怎么列"
msgid "Groups Membership" msgid "Groups Membership"
msgstr "用户组成员" msgstr "用户组成员"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:16
msgid "Groups"
msgstr "群组"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16 #: allianceauth/groupmanagement/templates/groupmanagement/groups.html:16
msgid "Description" msgid "Description"
@@ -596,7 +629,7 @@ msgstr "描述"
#: allianceauth/hrapplications/templates/hrapplications/management.html:85 #: allianceauth/hrapplications/templates/hrapplications/management.html:85
#: allianceauth/hrapplications/templates/hrapplications/management.html:130 #: allianceauth/hrapplications/templates/hrapplications/management.html:130
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/srp/templates/srp/data.html:97 #: allianceauth/srp/templates/srp/data.html:98
msgid "Status" msgid "Status"
msgstr "状态" msgstr "状态"
@@ -625,7 +658,11 @@ msgstr "查看成员"
msgid "Audit Members" msgid "Audit Members"
msgstr "编辑成员" msgstr "编辑成员"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:64 #: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
msgid "Copy Direct Join Link"
msgstr ""
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
msgid "No groups to list." msgid "No groups to list."
msgstr "无可用组" msgstr "无可用组"
@@ -654,37 +691,37 @@ msgstr "没有可用用户组"
msgid "Groups Management" msgid "Groups Management"
msgstr "用户组管理" msgstr "用户组管理"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
msgid "Join Requests" msgid "Join Requests"
msgstr "入组的请求" msgstr "入组的请求"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
msgid "Leave Requests" msgid "Leave Requests"
msgstr "离组的请求" msgstr "离组的请求"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
#: allianceauth/services/modules/openfire/forms.py:6 #: allianceauth/services/modules/openfire/forms.py:6
msgid "Group" msgid "Group"
msgstr "用户组" msgstr "用户组"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
msgid "Accept" msgid "Accept"
msgstr "接受" msgstr "接受"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
#: allianceauth/hrapplications/templates/hrapplications/view.html:85 #: allianceauth/hrapplications/templates/hrapplications/view.html:85
msgid "Reject" msgid "Reject"
msgstr "拒绝" msgstr "拒绝"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
msgid "No group add requests." msgid "No group add requests."
msgstr "没有加入用户组的请求,小老弟你是不是摇不到人" msgstr "没有加入用户组的请求,小老弟你是不是摇不到人"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142 #: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
msgid "No group leave requests." msgid "No group leave requests."
msgstr "没有离开用户组的请求,小老弟你人缘可以啊?" msgstr "没有离开用户组的请求,小老弟你人缘可以啊?"
@@ -692,11 +729,6 @@ msgstr "没有离开用户组的请求,小老弟你人缘可以啊?"
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "打开导航栏" msgstr "打开导航栏"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
#: allianceauth/templates/allianceauth/side-menu.html:23
msgid "Group Management"
msgstr "用户组管理"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21 #: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
msgid "Group Requests" msgid "Group Requests"
msgstr "用户组请求" msgstr "用户组请求"
@@ -705,91 +737,104 @@ msgstr "用户组请求"
msgid "Group Membership" msgid "Group Membership"
msgstr "用户组成员" msgstr "用户组成员"
#: allianceauth/groupmanagement/views.py:165 #: allianceauth/groupmanagement/views.py:162
#, python-format #, python-format
msgid "Removed user %(user)s from group %(group)s." msgid "Removed user %(user)s from group %(group)s."
msgstr "已将用户%(user)s从用户组%(group)s中移除" msgstr "已将用户%(user)s从用户组%(group)s中移除"
#: allianceauth/groupmanagement/views.py:167 #: allianceauth/groupmanagement/views.py:164
msgid "User does not exist in that group" msgid "User does not exist in that group"
msgstr "那个用户组中不存在这个用户" msgstr "那个用户组中不存在这个用户"
#: allianceauth/groupmanagement/views.py:170 #: allianceauth/groupmanagement/views.py:167
msgid "Group does not exist" msgid "Group does not exist"
msgstr "用户组不存在" msgstr "用户组不存在"
#: allianceauth/groupmanagement/views.py:197 #: allianceauth/groupmanagement/views.py:194
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to %(group)s." msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "已接受用户%(mainchar)s加入%(group)s的申请" msgstr "已接受用户%(mainchar)s加入%(group)s的申请"
#: allianceauth/groupmanagement/views.py:204 #: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:237 #: allianceauth/groupmanagement/views.py:234
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occurred while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s." "%(mainchar)s to %(group)s."
msgstr "在处理用户%(mainchar)s加入%(group)s的申请的过程中出现了一个搞不定的错误" msgstr "在处理用户%(mainchar)s加入%(group)s的申请的过程中出现了一个搞不定的错误"
#: allianceauth/groupmanagement/views.py:230 #: allianceauth/groupmanagement/views.py:227
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to %(group)s." msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "%(mainchar)s加入%(group)s的申请已拒绝" msgstr "%(mainchar)s加入%(group)s的申请已拒绝"
#: allianceauth/groupmanagement/views.py:266 #: allianceauth/groupmanagement/views.py:263
#, python-format #, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s." msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "%(mainchar)s加入%(group)s的申请已通过" msgstr "%(mainchar)s加入%(group)s的申请已通过"
#: allianceauth/groupmanagement/views.py:272 #: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:306 #: allianceauth/groupmanagement/views.py:303
#, python-format #, python-format
msgid "" msgid ""
"An unhandled error occured while processing the application from " "An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s." "%(mainchar)s to leave %(group)s."
msgstr "在处理%(mainchar)s离开%(group)s的请求时发生了搞不定的错误" msgstr "在处理%(mainchar)s离开%(group)s的程序时发生了未知的错误"
#: allianceauth/groupmanagement/views.py:299 #: allianceauth/groupmanagement/views.py:296
#, python-format #, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s." msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "%(mainchar)s离开%(group)s的请求已被拒绝" msgstr "%(mainchar)s离开%(group)s的请求已被拒绝"
#: allianceauth/groupmanagement/views.py:346 #: allianceauth/groupmanagement/views.py:342
#: allianceauth/groupmanagement/views.py:354
msgid "You cannot join that group" msgid "You cannot join that group"
msgstr "你无法加入那个用户组" msgstr "你无法加入那个用户组"
#: allianceauth/groupmanagement/views.py:370 #: allianceauth/groupmanagement/views.py:348
#: allianceauth/groupmanagement/views.py:408 msgid "You are already a member of that group."
msgstr "你已经是那个群组的一员了。"
#: allianceauth/groupmanagement/views.py:363
msgid "You already have a pending application for that group."
msgstr "你已经有了该组的未决申请"
#: allianceauth/groupmanagement/views.py:366
#: allianceauth/groupmanagement/views.py:404
#: allianceauth/hrapplications/templates/hrapplications/management.html:37 #: allianceauth/hrapplications/templates/hrapplications/management.html:37
#: allianceauth/hrapplications/templates/hrapplications/management.html:72 #: allianceauth/hrapplications/templates/hrapplications/management.html:72
#: allianceauth/hrapplications/templates/hrapplications/management.html:99 #: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:144 #: allianceauth/hrapplications/templates/hrapplications/management.html:144
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
#: allianceauth/hrapplications/templates/hrapplications/view.html:20 #: allianceauth/hrapplications/templates/hrapplications/view.html:20
#: allianceauth/srp/templates/srp/data.html:125 #: allianceauth/srp/templates/srp/data.html:134
#: allianceauth/srp/templates/srp/management.html:81 #: allianceauth/srp/templates/srp/management.html:81
msgid "Pending" msgid "Pending"
msgstr "待定" msgstr "待定"
#: allianceauth/groupmanagement/views.py:376 #: allianceauth/groupmanagement/views.py:372
#, python-format #, python-format
msgid "Applied to group %(group)s." msgid "Applied to group %(group)s."
msgstr "修改已经应用到%(group)s啦" msgstr "修改已经应用到%(group)s啦"
#: allianceauth/groupmanagement/views.py:387 #: allianceauth/groupmanagement/views.py:383
msgid "You cannot leave that group" msgid "You cannot leave that group"
msgstr "你无法离开那个用户组" msgstr "你无法离开那个用户组"
#: allianceauth/groupmanagement/views.py:392 #: allianceauth/groupmanagement/views.py:388
msgid "You are not a member of that group" msgid "You are not a member of that group"
msgstr "你不是那个用户组的成员" msgstr "你不是那个用户组的成员"
#: allianceauth/groupmanagement/views.py:414 #: allianceauth/groupmanagement/views.py:397
msgid "You already have a pending leave request for that group."
msgstr "你已经有了该组的未决离开请求"
#: allianceauth/groupmanagement/views.py:410
#, python-format #, python-format
msgid "Applied to leave group %(group)s." msgid "Applied to leave group %(group)s."
msgstr "已经离开群组%(group)s" msgstr "已经离开群组%(group)s"
#: allianceauth/hrapplications/auth_hooks.py:10 #: allianceauth/hrapplications/auth_hooks.py:13
msgid "Applications" msgid "Applications"
msgstr "申请" msgstr "申请"
@@ -846,7 +891,7 @@ msgstr "用户名"
#: allianceauth/hrapplications/templates/hrapplications/management.html:131 #: allianceauth/hrapplications/templates/hrapplications/management.html:131
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
#: allianceauth/hrapplications/templates/hrapplications/view.html:75 #: allianceauth/hrapplications/templates/hrapplications/view.html:75
#: allianceauth/srp/templates/srp/data.html:99 #: allianceauth/srp/templates/srp/data.html:100
#: allianceauth/srp/templates/srp/management.html:46 #: allianceauth/srp/templates/srp/management.html:46
msgid "Actions" msgid "Actions"
msgstr "操作" msgstr "操作"
@@ -856,7 +901,7 @@ msgstr "操作"
#: allianceauth/hrapplications/templates/hrapplications/management.html:147 #: allianceauth/hrapplications/templates/hrapplications/management.html:147
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
#: allianceauth/hrapplications/templates/hrapplications/view.html:16 #: allianceauth/hrapplications/templates/hrapplications/view.html:16
#: allianceauth/srp/templates/srp/data.html:117 #: allianceauth/srp/templates/srp/data.html:126
msgid "Approved" msgid "Approved"
msgstr "通过" msgstr "通过"
@@ -864,7 +909,7 @@ msgstr "通过"
#: allianceauth/hrapplications/templates/hrapplications/management.html:104 #: allianceauth/hrapplications/templates/hrapplications/management.html:104
#: allianceauth/hrapplications/templates/hrapplications/management.html:149 #: allianceauth/hrapplications/templates/hrapplications/management.html:149
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42 #: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
#: allianceauth/srp/templates/srp/data.html:121 #: allianceauth/srp/templates/srp/data.html:130
msgid "Rejected" msgid "Rejected"
msgstr "拒绝" msgstr "拒绝"
@@ -1130,10 +1175,6 @@ msgstr "对搞事时间节点%(opname)s的修改保存了朝令夕改你是
msgid "Permissions Audit" msgid "Permissions Audit"
msgstr "放行记录审计" msgstr "放行记录审计"
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:13
msgid "Back"
msgstr "返回"
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:22 #: allianceauth/permissions_tool/templates/permissions_tool/audit.html:22
msgid "User / Character" msgid "User / Character"
msgstr "用户/角色" msgstr "用户/角色"
@@ -1175,15 +1216,22 @@ msgstr "操作类型"
msgid "Users" msgid "Users"
msgstr "用户" msgstr "用户"
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
#: allianceauth/templates/allianceauth/side-menu.html:15
msgid "Groups"
msgstr "群组"
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:43 #: allianceauth/permissions_tool/templates/permissions_tool/overview.html:43
msgid "States" msgid "States"
msgstr "声望" msgstr "声望"
#: allianceauth/services/abstract.py:72
msgid "That service account already exists"
msgstr "该服务账户仍然存在"
#: allianceauth/services/abstract.py:104
msgid "Successfully set your {} password"
msgstr "成功修改了你的[]密码"
#: allianceauth/services/auth_hooks.py:11
msgid "Services"
msgstr "服务"
#: allianceauth/services/forms.py:6 #: allianceauth/services/forms.py:6
msgid "Name of Fleet:" msgid "Name of Fleet:"
msgstr "舰队名称" msgstr "舰队名称"
@@ -1244,19 +1292,111 @@ msgstr "密码"
msgid "Password must be at least 8 characters long." msgid "Password must be at least 8 characters long."
msgstr "密码至少要有8个字符啊你也太不注重安全啦" msgstr "密码至少要有8个字符啊你也太不注重安全啦"
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23 #: allianceauth/services/modules/discord/models.py:225
msgid "Discord Account Disabled"
msgstr ""
#: allianceauth/services/modules/discord/models.py:227
msgid ""
"Your Discord account was disabeled automatically by Auth. If you think this "
"was a mistake, please contact an admin."
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
msgid "Join the Discord server"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
msgid "Leave- and rejoin the Discord Server (Reset)"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
msgid "Leave the Discord server"
msgstr ""
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
msgid "Link Discord Server" msgid "Link Discord Server"
msgstr "链接到Discord服务器" msgstr "链接到Discord服务器"
#: allianceauth/services/modules/openfire/forms.py:7 #: allianceauth/services/modules/discord/views.py:30
msgid "Message" msgid "Deactivated Discord account."
msgstr "消息" msgstr "停用Discord账户"
#: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:59
msgid "An error occurred while processing your Discord account."
msgstr "在处理你的Discord账户时出错。"
#: allianceauth/services/modules/discord/views.py:102
msgid "Your Discord account has been successfully activated."
msgstr ""
#: allianceauth/services/modules/discord/views.py:108
msgid ""
"An error occurred while trying to activate your Discord account. Please try "
"again."
msgstr ""
#: allianceauth/services/modules/discourse/views.py:37
msgid "You are not authorized to access Discourse."
msgstr "你无权访问Discourse"
#: allianceauth/services/modules/discourse/views.py:42
msgid "You must have a main character set to access Discourse."
msgstr "你必须得有一个主要角色来访问Discourse"
#: allianceauth/services/modules/discourse/views.py:52
msgid ""
"No SSO payload or signature. Please contact support if this problem "
"persists."
msgstr "没有在Seat上检测到SSO。如果该问题依然存在请联系技术支持"
#: allianceauth/services/modules/discourse/views.py:62
#: allianceauth/services/modules/discourse/views.py:70
msgid "Invalid payload. Please contact support if this problem persists."
msgstr "无效的SSO验证。如果该问题依然存在请联系技术支持。"
#: allianceauth/services/modules/ips4/views.py:31
msgid "Activated IPSuite4 account."
msgstr "完成激活IPSuite4账户"
#: allianceauth/services/modules/ips4/views.py:40
#: allianceauth/services/modules/ips4/views.py:62
#: allianceauth/services/modules/ips4/views.py:83
#: allianceauth/services/modules/ips4/views.py:103
msgid "An error occurred while processing your IPSuite4 account."
msgstr "在处理你的IPSuite4账户时出错"
#: allianceauth/services/modules/ips4/views.py:53
msgid "Reset IPSuite4 password."
msgstr "重置IPSuite4密码"
#: allianceauth/services/modules/ips4/views.py:80
msgid "Set IPSuite4 password."
msgstr "修改IPSuite4密码"
#: allianceauth/services/modules/ips4/views.py:100
msgid "Deactivated IPSuite4 account."
msgstr "停用IPSuite4账户"
#: allianceauth/services/modules/openfire/auth_hooks.py:26
msgid "Jabber"
msgstr "Jabber"
#: allianceauth/services/modules/openfire/auth_hooks.py:78
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:6 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:6
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:11 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:11
msgid "Jabber Broadcast" msgid "Jabber Broadcast"
msgstr "Jabber广播" msgstr "Jabber广播"
#: allianceauth/services/modules/openfire/auth_hooks.py:91
msgid "Fleet Broadcast Formatter"
msgstr "舰队广播设置"
#: allianceauth/services/modules/openfire/forms.py:7
msgid "Message"
msgstr "消息"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:17 #: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:17
msgid "Broadcast Sent!!" msgid "Broadcast Sent!!"
msgstr "广播出去了!" msgstr "广播出去了!"
@@ -1265,6 +1405,76 @@ msgstr "广播出去了!"
msgid "Broadcast" msgid "Broadcast"
msgstr "广播" msgstr "广播"
#: allianceauth/services/modules/openfire/views.py:35
msgid "Activated jabber account."
msgstr "成功激活jabber账户"
#: allianceauth/services/modules/openfire/views.py:44
#: allianceauth/services/modules/openfire/views.py:57
#: allianceauth/services/modules/openfire/views.py:78
#: allianceauth/services/modules/openfire/views.py:151
msgid "An error occurred while processing your jabber account."
msgstr "在处理你的jabber账户时出错"
#: allianceauth/services/modules/openfire/views.py:70
msgid "Reset jabber password."
msgstr "重置jabber密码"
#: allianceauth/services/modules/openfire/views.py:119
#, python-format
msgid "Sent jabber broadcast to %s"
msgstr "已经将jabber广播送到了%s"
#: allianceauth/services/modules/openfire/views.py:148
msgid "Set jabber password."
msgstr "修改jabber密码"
#: allianceauth/services/modules/phpbb3/views.py:34
msgid "Activated forum account."
msgstr "成功激活论坛账户"
#: allianceauth/services/modules/phpbb3/views.py:43
#: allianceauth/services/modules/phpbb3/views.py:57
#: allianceauth/services/modules/phpbb3/views.py:80
#: allianceauth/services/modules/phpbb3/views.py:103
msgid "An error occurred while processing your forum account."
msgstr "在处理你的论坛账户时发生了一个错误"
#: allianceauth/services/modules/phpbb3/views.py:54
msgid "Deactivated forum account."
msgstr "停用论坛账户"
#: allianceauth/services/modules/phpbb3/views.py:71
msgid "Reset forum password."
msgstr "重置论坛密码"
#: allianceauth/services/modules/phpbb3/views.py:100
msgid "Set forum password."
msgstr "修改论坛密码"
#: allianceauth/services/modules/smf/views.py:34
msgid "Activated SMF account."
msgstr "成功激活SMF论坛账户"
#: allianceauth/services/modules/smf/views.py:43
#: allianceauth/services/modules/smf/views.py:58
#: allianceauth/services/modules/smf/views.py:80
#: allianceauth/services/modules/smf/views.py:103
msgid "An error occurred while processing your SMF account."
msgstr "在处理你的SMF论坛账户时发生了一个错误"
#: allianceauth/services/modules/smf/views.py:55
msgid "Deactivated SMF account."
msgstr "停用SMF论坛账户"
#: allianceauth/services/modules/smf/views.py:72
msgid "Reset SMF password."
msgstr "重置SMF密码"
#: allianceauth/services/modules/smf/views.py:100
msgid "Set SMF password."
msgstr "修改SMF论坛密码"
#: allianceauth/services/modules/teamspeak3/forms.py:14 #: allianceauth/services/modules/teamspeak3/forms.py:14
#, python-format #, python-format
msgid "Unable to locate user %s on server" msgid "Unable to locate user %s on server"
@@ -1288,6 +1498,47 @@ msgstr "加入服务器"
msgid "Continue" msgid "Continue"
msgstr "下一个" msgstr "下一个"
#: allianceauth/services/modules/teamspeak3/views.py:34
msgid "Activated TeamSpeak3 account."
msgstr "成功激活TeamSpeak3账户"
#: allianceauth/services/modules/teamspeak3/views.py:37
#: allianceauth/services/modules/teamspeak3/views.py:74
#: allianceauth/services/modules/teamspeak3/views.py:100
msgid "An error occurred while processing your TeamSpeak3 account."
msgstr "在处理你的TeamSpeak3账户时发生了错误"
#: allianceauth/services/modules/teamspeak3/views.py:71
msgid "Deactivated TeamSpeak3 account."
msgstr "停用TeamSpeak3账户"
#: allianceauth/services/modules/teamspeak3/views.py:97
msgid "Reset TeamSpeak3 permission key."
msgstr "重置TeamSpeak3授权秘钥"
#: allianceauth/services/modules/xenforo/views.py:30
msgid "Activated XenForo account."
msgstr "成功激活XenForo账户"
#: allianceauth/services/modules/xenforo/views.py:40
#: allianceauth/services/modules/xenforo/views.py:52
#: allianceauth/services/modules/xenforo/views.py:73
#: allianceauth/services/modules/xenforo/views.py:94
msgid "An error occurred while processing your XenForo account."
msgstr "在处理你的XenForo账户时发生了一个错误"
#: allianceauth/services/modules/xenforo/views.py:50
msgid "Deactivated XenForo account."
msgstr "停用XenForo论坛账户"
#: allianceauth/services/modules/xenforo/views.py:65
msgid "Reset XenForo account password."
msgstr "重置XenForo密码"
#: allianceauth/services/modules/xenforo/views.py:91
msgid "Changed XenForo password."
msgstr "修改XenForo密码"
#: allianceauth/services/templates/services/fleetformattertool.html:6 #: allianceauth/services/templates/services/fleetformattertool.html:6
msgid "Fleet Formatter Tool" msgid "Fleet Formatter Tool"
msgstr "起队工具" msgstr "起队工具"
@@ -1348,7 +1599,7 @@ msgstr "服务"
msgid "Domain" msgid "Domain"
msgstr "域名" msgstr "域名"
#: allianceauth/srp/auth_hooks.py:9 #: allianceauth/srp/auth_hooks.py:12
msgid "Ship Replacement" msgid "Ship Replacement"
msgstr "补损" msgstr "补损"
@@ -1362,7 +1613,7 @@ msgstr "集结时间"
msgid "Fleet Doctrine" msgid "Fleet Doctrine"
msgstr "舰队船型" msgstr "舰队船型"
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89 #: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
msgid "Additional Info" msgid "Additional Info"
msgstr "其他信息" msgstr "其他信息"
@@ -1391,63 +1642,63 @@ msgstr "创建补损舰队"
msgid "Give this link to the line members" msgid "Give this link to the line members"
msgstr "把这个链接发送给火力狗们" msgstr "把这个链接发送给火力狗们"
#: allianceauth/srp/templates/srp/data.html:48 #: allianceauth/srp/templates/srp/data.html:49
msgid "SRP Fleet Data" msgid "SRP Fleet Data"
msgstr "舰队补损信息" msgstr "舰队补损信息"
#: allianceauth/srp/templates/srp/data.html:53 #: allianceauth/srp/templates/srp/data.html:54
msgid "Mark Incomplete" msgid "Mark Incomplete"
msgstr "标记为未完成" msgstr "标记为未完成"
#: allianceauth/srp/templates/srp/data.html:57 #: allianceauth/srp/templates/srp/data.html:58
msgid "Mark Completed" msgid "Mark Completed"
msgstr "标记为已完成" msgstr "标记为已完成"
#: allianceauth/srp/templates/srp/data.html:69 #: allianceauth/srp/templates/srp/data.html:70
#: allianceauth/srp/templates/srp/data.html:145 #: allianceauth/srp/templates/srp/data.html:156
msgid "Total Losses:" msgid "Total Losses:"
msgstr "损失总额:" msgstr "损失总额:"
#: allianceauth/srp/templates/srp/data.html:70 #: allianceauth/srp/templates/srp/data.html:71
#: allianceauth/srp/templates/srp/data.html:146 #: allianceauth/srp/templates/srp/data.html:157
#: allianceauth/srp/templates/srp/management.html:30 #: allianceauth/srp/templates/srp/management.html:30
msgid "Total ISK Cost:" msgid "Total ISK Cost:"
msgstr "ISK花费总额" msgstr "ISK花费总额"
#: allianceauth/srp/templates/srp/data.html:78 #: allianceauth/srp/templates/srp/data.html:79
#: allianceauth/srp/templates/srp/data.html:154 #: allianceauth/srp/templates/srp/data.html:165
msgid "Are you sure you want to delete SRP requests?" msgid "Are you sure you want to delete SRP requests?"
msgstr "老哥,你确定要删了补损请求么?" msgstr "老哥,你确定要删了补损请求么?"
#: allianceauth/srp/templates/srp/data.html:87 #: allianceauth/srp/templates/srp/data.html:88
msgid "Pilot Name" msgid "Pilot Name"
msgstr "玩家ID" msgstr "玩家ID"
#: allianceauth/srp/templates/srp/data.html:88 #: allianceauth/srp/templates/srp/data.html:89
msgid "Killboard Link" msgid "Killboard Link"
msgstr "KB网链接" msgstr "KB网链接"
#: allianceauth/srp/templates/srp/data.html:90 #: allianceauth/srp/templates/srp/data.html:91
msgid "Ship Type" msgid "Ship Type"
msgstr "船型" msgstr "船型"
#: allianceauth/srp/templates/srp/data.html:91 #: allianceauth/srp/templates/srp/data.html:92
msgid "Killboard Loss Amt" msgid "Killboard Loss Amt"
msgstr "KB网总损失" msgstr "KB网总损失"
#: allianceauth/srp/templates/srp/data.html:92 #: allianceauth/srp/templates/srp/data.html:93
msgid "SRP ISK Cost" msgid "SRP ISK Cost"
msgstr "补损ISK花费" msgstr "补损ISK花费"
#: allianceauth/srp/templates/srp/data.html:93 #: allianceauth/srp/templates/srp/data.html:94
msgid "Click value to edit Enter to save & next ESC to cancel" msgid "Click value to edit Enter to save & next ESC to cancel"
msgstr "点击数值就可以编辑啦按回车确认按ESC取消" msgstr "点击数值就可以编辑啦按回车确认按ESC取消"
#: allianceauth/srp/templates/srp/data.html:96 #: allianceauth/srp/templates/srp/data.html:97
msgid "Post Time" msgid "Post Time"
msgstr "发布时间" msgstr "发布时间"
#: allianceauth/srp/templates/srp/data.html:163 #: allianceauth/srp/templates/srp/data.html:174
msgid "No SRP requests for this fleet." msgid "No SRP requests for this fleet."
msgstr "这次起队没有补损请求!大捷" msgstr "这次起队没有补损请求!大捷"
@@ -1638,43 +1889,35 @@ msgid "Current"
msgstr "当前版本" msgstr "当前版本"
#: allianceauth/templates/allianceauth/admin-status/overview.html:40 #: allianceauth/templates/allianceauth/admin-status/overview.html:40
msgid "Latest Major" msgid "Latest Stable"
msgstr "最新主版本号" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:46 #: allianceauth/templates/allianceauth/admin-status/overview.html:46
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
msgid "Update available" msgid "Update available"
msgstr "有更新!" msgstr "有更新!"
#: allianceauth/templates/allianceauth/admin-status/overview.html:50 #: allianceauth/templates/allianceauth/admin-status/overview.html:51
msgid "Latest Minor" msgid "Latest Pre-Release"
msgstr "最新小版本号" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:60 #: allianceauth/templates/allianceauth/admin-status/overview.html:57
msgid "Latest Patch" msgid "Pre-Release available"
msgstr "最新补丁版本" msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:73 #: allianceauth/templates/allianceauth/admin-status/overview.html:65
msgid "Task Queue" msgid "Task Queue"
msgstr "任务队列" msgstr "任务队列"
#: allianceauth/templates/allianceauth/admin-status/overview.html:90 #: allianceauth/templates/allianceauth/admin-status/overview.html:82
msgid "Error retrieving task queue length" msgid "Error retrieving task queue length"
msgstr "获取任务队列长度的时候出错啦!" msgstr "获取任务队列长度的时候出错啦!"
#: allianceauth/templates/allianceauth/admin-status/overview.html:92 #: allianceauth/templates/allianceauth/admin-status/overview.html:84
#, python-format #, python-format
msgid "%(tasks)s task" msgid "%(tasks)s task"
msgid_plural "%(tasks)s tasks" msgid_plural "%(tasks)s tasks"
msgstr[0] "%(tasks)s个任务" msgstr[0] "%(tasks)s个任务"
#: allianceauth/templates/allianceauth/help.html:4
#: allianceauth/templates/allianceauth/help.html:9
#: allianceauth/templates/allianceauth/side-menu.html:34
msgid "Help"
msgstr "帮助"
#: allianceauth/templates/allianceauth/night-toggle.html:3 #: allianceauth/templates/allianceauth/night-toggle.html:3
msgid "Night" msgid "Night"
msgstr "暗色皮肤" msgstr "暗色皮肤"

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Notifications" %}{% endblock %} {% block page_title %}{% trans "Notifications" %}{% endblock %}

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "View Notification" %}{% endblock page_title %} {% block page_title %}{% trans "View Notification" %}{% endblock page_title %}

View File

@@ -7,7 +7,7 @@ from . import urls
class OpTimerboardMenu(MenuItemHook): class OpTimerboardMenu(MenuItemHook):
def __init__(self): def __init__(self):
MenuItemHook.__init__(self, _('Fleet Operations'), MenuItemHook.__init__(self, _('Fleet Operations'),
'fa fa-exclamation fa-fw', 'fas fa-exclamation fa-fw',
'optimer:view', 'optimer:view',
navactive=['optimer:']) navactive=['optimer:'])

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
@@ -36,9 +36,15 @@
{% block extra_script %} {% block extra_script %}
$('#id_start').datetimepicker({ $('#id_start').datetimepicker({
lang: '{{ LANGUAGE_CODE }}', setlocale: '{{ LANGUAGE_CODE }}',
maskInput: true, {% if NIGHT_MODE %}
format: 'Y-m-d H:i',minDate:0 theme: 'dark',
{% else %}
theme: 'default',
{% endif %}
mask: true,
format: 'Y-m-d H:i',
minDate: 0
}); });
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -1,5 +1,5 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
@@ -41,7 +41,7 @@
{% include 'bundles/moment-js.html' with locale=True %} {% include 'bundles/moment-js.html' with locale=True %}
<script src="{% static 'js/timers.js' %}"></script> <script src="{% static 'js/timers.js' %}"></script>
<script type="text/javascript"> <script type="application/javascript">
// Data // Data
var timers = [ var timers = [
{% for op in optimer %} {% for op in optimer %}
@@ -53,7 +53,7 @@
{% endfor %} {% endfor %}
]; ];
</script> </script>
<script type="text/javascript"> <script type="application/javascript">
timedUpdate(); timedUpdate();
setAllLocalTimes(); setAllLocalTimes();

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
@@ -44,9 +44,15 @@
{% block extra_script %} {% block extra_script %}
$('#id_start').datetimepicker({ $('#id_start').datetimepicker({
lang: '{{ LANGUAGE_CODE }}', setlocale: '{{ LANGUAGE_CODE }}',
maskInput: true, {% if NIGHT_MODE %}
format: 'Y-m-d H:i',minDate:0 theme: 'dark',
{% else %}
theme: 'default',
{% endif %}
mask: true,
format: 'Y-m-d H:i',
minDate: 0
}); });
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -8,7 +8,7 @@ class PermissionsTool(MenuItemHook):
def __init__(self): def __init__(self):
MenuItemHook.__init__(self, MenuItemHook.__init__(self,
'Permissions Audit', 'Permissions Audit',
'fa fa-key fa-id-card', 'fas fa-id-card fa-fw',
'permissions_tool:overview', 'permissions_tool:overview',
order=400, order=400,
navactive=['permissions_tool:']) navactive=['permissions_tool:'])

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{{ permission.permission.codename }} - {% trans "Permissions Audit" %}{% endblock page_title %} {% block page_title %}{{ permission.permission.codename }} - {% trans "Permissions Audit" %}{% endblock page_title %}
@@ -47,7 +47,7 @@
{% block extra_javascript %} {% block extra_javascript %}
{% include 'bundles/datatables-js.html' %} {% include 'bundles/datatables-js.html' %}
<script type="text/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script> <script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
{% endblock %} {% endblock %}
{% block extra_css %} {% block extra_css %}

View File

@@ -1,6 +1,6 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load static %}
{% load i18n %} {% load i18n %}
{% block page_title %}{% trans "Permissions Overview" %}{% endblock page_title %} {% block page_title %}{% trans "Permissions Overview" %}{% endblock page_title %}
@@ -80,7 +80,7 @@
{% block extra_javascript %} {% block extra_javascript %}
{% include 'bundles/datatables-js.html' %} {% include 'bundles/datatables-js.html' %}
<script type="text/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script> <script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
{% endblock %} {% endblock %}
{% block extra_css %} {% block extra_css %}

View File

@@ -41,7 +41,7 @@ class PermissionsToolViewsTestCase(WebTest):
response_content = response.content.decode('utf-8') response_content = response.content.decode('utf-8')
self.assertInHTML('<li><a class="active" href="/permissions/overview/">' self.assertInHTML('<li><a class="active" href="/permissions/overview/">'
'<i class="fa fa-key fa-id-card"></i> Permissions Audit</a></li>', response_content) '<i class="fas fa-id-card fa-fw"></i> Permissions Audit</a></li>', response_content)
def test_permissions_overview(self): def test_permissions_overview(self):
self.app.set_user(self.member) self.app.set_user(self.member)

View File

@@ -1,5 +1,6 @@
import os import os
from celery import Celery from celery import Celery
from celery.app import trace
# set the default Django settings module for the 'celery' program. # set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings.local') os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings.local')
@@ -27,3 +28,6 @@ app.conf.ONCE = {
# Load task modules from all registered Django app configs. # Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
# Remove result from default log message on task success
trace.LOG_SUCCESS = "Task %(name)s[%(id)s] succeeded in %(runtime)ss"

View File

@@ -64,12 +64,12 @@ BASE_DIR = os.path.dirname(PROJECT_DIR)
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
] ]
ROOT_URLCONF = 'allianceauth.urls' ROOT_URLCONF = 'allianceauth.urls'
@@ -86,6 +86,8 @@ LANGUAGES = (
('zh-hans', ugettext('Chinese Simplified')), ('zh-hans', ugettext('Chinese Simplified')),
('ru', ugettext('Russian')), ('ru', ugettext('Russian')),
('ko', ugettext('Korean')), ('ko', ugettext('Korean')),
('fr', ugettext('French')),
('ja', ugettext('Japanese')),
) )
TEMPLATES = [ TEMPLATES = [
@@ -103,8 +105,7 @@ TEMPLATES = [
'django.template.context_processors.media', 'django.template.context_processors.media',
'django.template.context_processors.static', 'django.template.context_processors.static',
'django.template.context_processors.tz', 'django.template.context_processors.tz',
'allianceauth.notifications.context_processors.user_notification_count', 'allianceauth.notifications.context_processors.user_notification_count',
'allianceauth.groupmanagement.context_processors.can_manage_groups',
'allianceauth.context_processors.auth_settings', 'allianceauth.context_processors.auth_settings',
], ],
}, },
@@ -139,6 +140,8 @@ AUTHENTICATION_BACKENDS = ['allianceauth.authentication.backends.StateBackend',
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'
LANGUAGE_COOKIE_AGE = 1209600
TIME_ZONE = 'UTC' TIME_ZONE = 'UTC'
USE_I18N = True USE_I18N = True

View File

@@ -45,6 +45,7 @@ DATABASES['default'] = {
ESI_SSO_CLIENT_ID = '' ESI_SSO_CLIENT_ID = ''
ESI_SSO_CLIENT_SECRET = '' ESI_SSO_CLIENT_SECRET = ''
ESI_SSO_CALLBACK_URL = '' ESI_SSO_CALLBACK_URL = ''
ESI_USER_CONTACT_EMAIL = '' # A server maintainer that CCP can contact in case of issues.
# By default emails are validated before new users can log in. # By default emails are validated before new users can log in.
# It's recommended to use a free service like SparkPost or Elastic Email to send email. # It's recommended to use a free service like SparkPost or Elastic Email to send email.

View File

@@ -9,7 +9,7 @@ class Services(MenuItemHook):
def __init__(self): def __init__(self):
MenuItemHook.__init__(self, MenuItemHook.__init__(self,
_('Services'), _('Services'),
'fa fa-cogs fa-fw', 'fas fa-cogs fa-fw',
'services:services', 100) 'services:services', 100)
def render(self, request): def render(self, request):

View File

@@ -139,6 +139,11 @@ class MenuItemHook:
self.url_name = url_name self.url_name = url_name
self.template = 'public/menuitem.html' self.template = 'public/menuitem.html'
self.order = order if order is not None else 9999 self.order = order if order is not None else 9999
# count is an integer shown next to the menu item as badge when count != None
# apps need to set the count in their child class, e.g. in render() method
self.count = None
navactive = navactive or [] navactive = navactive or []
navactive.append(url_name) navactive.append(url_name)
self.navactive = navactive self.navactive = navactive

View File

@@ -33,7 +33,8 @@ class DiscordService(ServicesHook):
if self.user_has_account(user): if self.user_has_account(user):
logger.debug('Deleting user %s %s account', user, self.name) logger.debug('Deleting user %s %s account', user, self.name)
tasks.delete_user.apply_async( tasks.delete_user.apply_async(
kwargs={'user_pk': user.pk}, priority=SINGLE_TASK_PRIORITY kwargs={'user_pk': user.pk, 'notify_user': notify_user},
priority=SINGLE_TASK_PRIORITY
) )
def render_services_ctrl(self, request): def render_services_ctrl(self, request):
@@ -60,13 +61,21 @@ class DiscordService(ServicesHook):
) )
def service_active_for_user(self, user): def service_active_for_user(self, user):
return user.has_perm(self.access_perm) has_perms = user.has_perm(self.access_perm)
logger.debug("User %s has service permission: %s", user, has_perms)
return has_perms
def sync_nickname(self, user): def sync_nickname(self, user):
logger.debug('Syncing %s nickname for user %s', self.name, user) logger.debug('Syncing %s nickname for user %s', self.name, user)
if self.user_has_account(user): if self.user_has_account(user):
tasks.update_nickname.apply_async( tasks.update_nickname.apply_async(
kwargs={'user_pk': user.pk}, priority=SINGLE_TASK_PRIORITY kwargs={
'user_pk': user.pk,
# since the new nickname is not yet in the DB we need to
# provide it manually to the task
'nickname': DiscordUser.objects.user_formatted_nick(user)
},
priority=SINGLE_TASK_PRIORITY
) )
def sync_nicknames_bulk(self, users: list): def sync_nicknames_bulk(self, users: list):
@@ -84,10 +93,16 @@ class DiscordService(ServicesHook):
tasks.update_all_groups.delay() tasks.update_all_groups.delay()
def update_groups(self, user): def update_groups(self, user):
logger.debug('Processing %s groups for %s', self.name, user) logger.debug('Processing %s groups for %s', self.name, user)
if self.user_has_account(user): if self.user_has_account(user):
tasks.update_groups.apply_async( tasks.update_groups.apply_async(
kwargs={'user_pk': user.pk}, priority=SINGLE_TASK_PRIORITY kwargs={
'user_pk': user.pk,
# since state changes may not yet be in the DB we need to
# provide the new state name manually to the task
'state_name': user.profile.state.name
},
priority=SINGLE_TASK_PRIORITY
) )
def update_groups_bulk(self, users: list): def update_groups_bulk(self, users: list):

View File

@@ -3,33 +3,38 @@ from ..utils import clean_setting
# Base URL for all API calls. Must end with /. # Base URL for all API calls. Must end with /.
DISCORD_API_BASE_URL = clean_setting( DISCORD_API_BASE_URL = clean_setting(
'DISCORD_API_BASE_URL', 'https://discordapp.com/api/' 'DISCORD_API_BASE_URL', 'https://discord.com/api/'
) )
# Low level timeout for requests to the Discord API in ms # Low level connecttimeout for requests to the Discord API in seconds
DISCORD_API_TIMEOUT = clean_setting( DISCORD_API_TIMEOUT_CONNECT = clean_setting(
'DISCORD_API_TIMEOUT', 5000 'DISCORD_API_TIMEOUT', 5
)
# Low level read timeout for requests to the Discord API in seconds
DISCORD_API_TIMEOUT_READ = clean_setting(
'DISCORD_API_TIMEOUT', 30
) )
# Base authorization URL for Discord Oauth # Base authorization URL for Discord Oauth
DISCORD_OAUTH_BASE_URL = clean_setting( DISCORD_OAUTH_BASE_URL = clean_setting(
'DISCORD_OAUTH_BASE_URL', 'https://discordapp.com/api/oauth2/authorize' 'DISCORD_OAUTH_BASE_URL', 'https://discord.com/api/oauth2/authorize'
) )
# Base authorization URL for Discord Oauth # Base authorization URL for Discord Oauth
DISCORD_OAUTH_TOKEN_URL = clean_setting( DISCORD_OAUTH_TOKEN_URL = clean_setting(
'DISCORD_OAUTH_TOKEN_URL', 'https://discordapp.com/api/oauth2/token' 'DISCORD_OAUTH_TOKEN_URL', 'https://discord.com/api/oauth2/token'
) )
# How long the Discord guild names retrieved from the server are # How long the Discord guild names retrieved from the server are
# caches locally in milliseconds. # caches locally in seconds.
DISCORD_GUILD_NAME_CACHE_MAX_AGE = clean_setting( DISCORD_GUILD_NAME_CACHE_MAX_AGE = clean_setting(
'DISCORD_GUILD_NAME_CACHE_MAX_AGE', 3600 * 1 * 1000 'DISCORD_GUILD_NAME_CACHE_MAX_AGE', 3600 * 24
) )
# How long Discord roles retrieved from the server are caches locally in milliseconds. # How long Discord roles retrieved from the server are caches locally in seconds.
DISCORD_ROLES_CACHE_MAX_AGE = clean_setting( DISCORD_ROLES_CACHE_MAX_AGE = clean_setting(
'DISCORD_ROLES_CACHE_MAX_AGE', 3600 * 1 * 1000 'DISCORD_ROLES_CACHE_MAX_AGE', 3600 * 1
) )
# Turns off creation of new roles. In case the rate limit for creating roles is # Turns off creation of new roles. In case the rate limit for creating roles is

View File

@@ -15,7 +15,8 @@ from allianceauth import __title__ as AUTH_TITLE, __url__, __version__
from .. import __title__ from .. import __title__
from .app_settings import ( from .app_settings import (
DISCORD_API_BASE_URL, DISCORD_API_BASE_URL,
DISCORD_API_TIMEOUT, DISCORD_API_TIMEOUT_CONNECT,
DISCORD_API_TIMEOUT_READ,
DISCORD_DISABLE_ROLE_CREATION, DISCORD_DISABLE_ROLE_CREATION,
DISCORD_GUILD_NAME_CACHE_MAX_AGE, DISCORD_GUILD_NAME_CACHE_MAX_AGE,
DISCORD_OAUTH_BASE_URL, DISCORD_OAUTH_BASE_URL,
@@ -46,6 +47,9 @@ DURATION_CONTINGENCY = 500
# time until next reset is below this threshold # time until next reset is below this threshold
WAIT_THRESHOLD = 250 WAIT_THRESHOLD = 250
# Minimum wait duration when doing a blocking wait
MINIMUM_BLOCKING_WAIT = 50
# If the rate limit resets soon we will wait it out and then retry to # If the rate limit resets soon we will wait it out and then retry to
# either get a remaining request from our cached counter # either get a remaining request from our cached counter
# or again wait out a short reset time and retry again. # or again wait out a short reset time and retry again.
@@ -176,12 +180,19 @@ class DiscordClient:
r = self._api_request(method='get', route=route) r = self._api_request(method='get', route=route)
return r.json() return r.json()
def guild_name(self, guild_id: int) -> str: def guild_name(self, guild_id: int, use_cache: bool = True) -> str:
"""returns the name of this guild (cached) """returns the name of this guild (cached)
or an empty string if something went wrong or an empty string if something went wrong
Params:
- guild_id: ID of current guild
- use_cache: When set to False will force an API call to get the server name
""" """
key_name = self._guild_name_cache_key(guild_id) key_name = self._guild_name_cache_key(guild_id)
guild_name = self._redis_decode(self._redis.get(key_name)) if use_cache:
guild_name = self._redis_decode(self._redis.get(key_name))
else:
guild_name = None
if not guild_name: if not guild_name:
guild_infos = self.guild_infos(guild_id) guild_infos = self.guild_infos(guild_id)
if 'name' in guild_infos: if 'name' in guild_infos:
@@ -189,7 +200,7 @@ class DiscordClient:
self._redis.set( self._redis.set(
name=key_name, name=key_name,
value=guild_name, value=guild_name,
px=DISCORD_GUILD_NAME_CACHE_MAX_AGE ex=DISCORD_GUILD_NAME_CACHE_MAX_AGE
) )
else: else:
guild_name = '' guild_name = ''
@@ -226,7 +237,7 @@ class DiscordClient:
self._redis.set( self._redis.set(
name=cache_key, name=cache_key,
value=json.dumps(roles), value=json.dumps(roles),
px=DISCORD_ROLES_CACHE_MAX_AGE ex=DISCORD_ROLES_CACHE_MAX_AGE
) )
return roles return roles
@@ -270,6 +281,11 @@ class DiscordClient:
gen_key = cls._generate_hash(f'{guild_id}') gen_key = cls._generate_hash(f'{guild_id}')
return f'{cls._KEYPREFIX_GUILD_ROLES}__{gen_key}' return f'{cls._KEYPREFIX_GUILD_ROLES}__{gen_key}'
def match_role_from_name(self, guild_id: int, role_name: str) -> dict:
"""returns Discord role matching the given name or an empty dict"""
guild_roles = DiscordRoles(self.guild_roles(guild_id))
return guild_roles.role_by_name(role_name)
def match_or_create_roles_from_names(self, guild_id: int, role_names: list) -> list: def match_or_create_roles_from_names(self, guild_id: int, role_names: list) -> list:
"""returns Discord roles matching the given names """returns Discord roles matching the given names
@@ -277,6 +293,7 @@ class DiscordClient:
Will try to match with existing roles names Will try to match with existing roles names
Non-existing roles will be created, then created flag will be True Non-existing roles will be created, then created flag will be True
Params: Params:
- guild_id: ID of guild - guild_id: ID of guild
- role_names: list of name strings each defining a role - role_names: list of name strings each defining a role
@@ -307,6 +324,7 @@ class DiscordClient:
Will try to match with existing roles names Will try to match with existing roles names
Non-existing roles will be created, then created flag will be True Non-existing roles will be created, then created flag will be True
Params: Params:
- guild_id: ID of guild - guild_id: ID of guild
- role_name: strings defining name of a role - role_name: strings defining name of a role
@@ -537,7 +555,7 @@ class DiscordClient:
args = { args = {
'url': url, 'url': url,
'headers': headers, 'headers': headers,
'timeout': DISCORD_API_TIMEOUT / 1000 'timeout': (DISCORD_API_TIMEOUT_CONNECT, DISCORD_API_TIMEOUT_READ)
} }
if data: if data:
args['json'] = data args['json'] = data
@@ -604,8 +622,11 @@ class DiscordClient:
name=self._KEY_GLOBAL_RATE_LIMIT_REMAINING, name=self._KEY_GLOBAL_RATE_LIMIT_REMAINING,
value=RATE_LIMIT_MAX_REQUESTS, value=RATE_LIMIT_MAX_REQUESTS,
px=RATE_LIMIT_RESETS_AFTER + DURATION_CONTINGENCY px=RATE_LIMIT_RESETS_AFTER + DURATION_CONTINGENCY
) )
resets_in = self._redis.pttl(self._KEY_GLOBAL_RATE_LIMIT_REMAINING) resets_in = max(
MINIMUM_BLOCKING_WAIT,
self._redis.pttl(self._KEY_GLOBAL_RATE_LIMIT_REMAINING)
)
if requests_remaining >= 0: if requests_remaining >= 0:
logger.debug( logger.debug(
'%s: Got one of %d remaining requests until reset in %s ms', '%s: Got one of %d remaining requests until reset in %s ms',
@@ -615,7 +636,7 @@ class DiscordClient:
) )
return requests_remaining return requests_remaining
elif resets_in < WAIT_THRESHOLD: elif resets_in < WAIT_THRESHOLD:
sleep(resets_in / 1000) sleep(resets_in / 1000)
logger.debug( logger.debug(
'%s: No requests remaining until reset in %d ms. ' '%s: No requests remaining until reset in %d ms. '

View File

@@ -33,7 +33,7 @@ logger = set_logger_to_file(
) )
MODULE_PATH = 'allianceauth.services.modules.discord.discord_client.client' MODULE_PATH = 'allianceauth.services.modules.discord.discord_client.client'
API_BASE_URL = 'https://discordapp.com/api/' API_BASE_URL = 'https://discord.com/api/'
TEST_RETRY_AFTER = 3000 TEST_RETRY_AFTER = 3000
@@ -50,6 +50,12 @@ mock_redis = MagicMock(**{
}) })
# default mock function to simulate sleep
def my_sleep(value):
if value < 0:
raise ValueError('sleep length must be non-negative')
class DiscordClient2(DiscordClient): class DiscordClient2(DiscordClient):
"""Variant that overwrites lua wrappers with dummies for easier testing""" """Variant that overwrites lua wrappers with dummies for easier testing"""
@@ -274,6 +280,8 @@ class TestGuildGetName(TestCase):
client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis) client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis)
result = client.guild_name(TEST_GUILD_ID) result = client.guild_name(TEST_GUILD_ID)
self.assertEqual(result, guild_name) self.assertEqual(result, guild_name)
self.assertTrue(my_mock_redis.get.called)
self.assertFalse(my_mock_redis.set.called)
@patch(MODULE_PATH + '.DiscordClient.guild_infos') @patch(MODULE_PATH + '.DiscordClient.guild_infos')
def test_fetches_from_server_if_not_found_in_cache_and_stores_in_cache( def test_fetches_from_server_if_not_found_in_cache_and_stores_in_cache(
@@ -285,6 +293,20 @@ class TestGuildGetName(TestCase):
client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis) client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis)
result = client.guild_name(TEST_GUILD_ID) result = client.guild_name(TEST_GUILD_ID)
self.assertEqual(result, guild_name) self.assertEqual(result, guild_name)
self.assertTrue(my_mock_redis.get.called)
self.assertTrue(my_mock_redis.set.called)
@patch(MODULE_PATH + '.DiscordClient.guild_infos')
def test_fetches_from_server_if_asked_to_ignore_cache_and_stores_in_cache(
self, mock_guild_get_infos
):
guild_name = 'Omega'
my_mock_redis = MagicMock(**{'get.return_value': False})
mock_guild_get_infos.return_value = {'id': TEST_GUILD_ID, 'name': guild_name}
client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis)
result = client.guild_name(TEST_GUILD_ID, use_cache=False)
self.assertFalse(my_mock_redis.get.called)
self.assertEqual(result, guild_name)
self.assertTrue(my_mock_redis.set.called) self.assertTrue(my_mock_redis.set.called)
@patch(MODULE_PATH + '.DiscordClient.guild_infos') @patch(MODULE_PATH + '.DiscordClient.guild_infos')
@@ -296,6 +318,7 @@ class TestGuildGetName(TestCase):
client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis) client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis)
result = client.guild_name(TEST_GUILD_ID) result = client.guild_name(TEST_GUILD_ID)
self.assertEqual(result, '') self.assertEqual(result, '')
self.assertTrue(my_mock_redis.get.called)
self.assertFalse(my_mock_redis.set.called) self.assertFalse(my_mock_redis.set.called)
@@ -838,9 +861,45 @@ class TestGuildMemberRemoveRole(TestCase):
self.assertFalse(result) self.assertFalse(result)
class TestMatchGuildRolesToName(TestCase):
def setUp(self):
self.url = f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles'
@requests_mock.Mocker()
def test_return_role_if_known(self, requests_mocker):
my_mock_redis = MagicMock(**{
'get.return_value': None,
'pttl.return_value': -1,
})
requests_mocker.get(
url=self.url,
request_headers=DEFAULT_REQUEST_HEADERS,
json=ALL_ROLES
)
client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis)
result = client.match_role_from_name(TEST_GUILD_ID, "alpha")
self.assertDictEqual(result, ROLE_ALPHA)
@requests_mock.Mocker()
def test_return_empty_dict_if_not_known(self, requests_mocker):
my_mock_redis = MagicMock(**{
'get.return_value': None,
'pttl.return_value': -1,
})
requests_mocker.get(
url=self.url,
request_headers=DEFAULT_REQUEST_HEADERS,
json=ALL_ROLES
)
client = DiscordClient2(TEST_BOT_TOKEN, my_mock_redis)
result = client.match_role_from_name(TEST_GUILD_ID, "unknown")
self.assertDictEqual(result, dict())
@patch(MODULE_PATH + '.DiscordClient.create_guild_role') @patch(MODULE_PATH + '.DiscordClient.create_guild_role')
@patch(MODULE_PATH + '.DiscordClient.guild_roles') @patch(MODULE_PATH + '.DiscordClient.guild_roles')
class TestMatchGuildRolesToName(TestCase): class TestMatchOrCreateGuildRolesToName(TestCase):
def test_return_role_if_known( def test_return_role_if_known(
self, mock_guild_get_roles, mock_guild_create_role, self, mock_guild_get_roles, mock_guild_create_role,
@@ -890,7 +949,7 @@ class TestMatchGuildRolesToName(TestCase):
@patch(MODULE_PATH + '.DiscordClient.create_guild_role') @patch(MODULE_PATH + '.DiscordClient.create_guild_role')
@patch(MODULE_PATH + '.DiscordClient.guild_roles') @patch(MODULE_PATH + '.DiscordClient.guild_roles')
class TestMatchGuildRolesToNames(TestCase): class TestMatchOrCreateGuildRolesToNames(TestCase):
def test_return_roles_if_known( def test_return_roles_if_known(
self, mock_guild_get_roles, mock_guild_create_role, self, mock_guild_get_roles, mock_guild_create_role,
@@ -1034,6 +1093,42 @@ class TestRateLimitMechanic(TestCase):
requests_mocker.post( requests_mocker.post(
f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role
) )
mock_sleep.side_effect = my_sleep
my_mock_redis = MagicMock(**{'pttl.side_effect': my_redis_pttl_2})
mock_redis_decr_or_set.side_effect = my_redis_decr_or_set
client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis)
result = client.create_guild_role(
guild_id=TEST_GUILD_ID, role_name=self.my_role['name']
)
self.assertDictEqual(result, self.my_role)
self.assertTrue(mock_sleep.called)
@patch(MODULE_PATH + '.sleep')
def test_wait_if_reset_happens_soon_and_sleep_must_not_be_negative(
self, requests_mocker, mock_sleep, mock_redis_decr_or_set
):
counter = 0
def my_redis_pttl_2(name: str):
if name == DiscordClient._KEY_GLOBAL_BACKOFF_UNTIL:
return -1
else:
return -1
def my_redis_decr_or_set(**kwargs):
nonlocal counter
counter += 1
if counter < 2:
return -1
else:
return 5
requests_mocker.post(
f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role
)
mock_sleep.side_effect = my_sleep
my_mock_redis = MagicMock(**{'pttl.side_effect': my_redis_pttl_2}) my_mock_redis = MagicMock(**{'pttl.side_effect': my_redis_pttl_2})
mock_redis_decr_or_set.side_effect = my_redis_decr_or_set mock_redis_decr_or_set.side_effect = my_redis_decr_or_set
client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis) client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis)
@@ -1075,6 +1170,7 @@ class TestRateLimitMechanic(TestCase):
requests_mocker.post( requests_mocker.post(
f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role
) )
mock_sleep.side_effect = my_sleep
my_mock_redis = MagicMock(**{'pttl.side_effect': my_redis_pttl_2}) my_mock_redis = MagicMock(**{'pttl.side_effect': my_redis_pttl_2})
mock_redis_decr_or_set.return_value = -1 mock_redis_decr_or_set.return_value = -1
client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis) client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis)
@@ -1208,7 +1304,8 @@ class TestBackoffHandling(TestCase):
requests_mocker.post( requests_mocker.post(
f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role f'{API_BASE_URL}guilds/{TEST_GUILD_ID}/roles', json=self.my_role
) )
retry_after = 50 retry_after = 50
mock_sleep.side_effect = my_sleep
my_mock_redis = MagicMock(**{'pttl.return_value': retry_after}) my_mock_redis = MagicMock(**{'pttl.return_value': retry_after})
mock_redis_decr_or_set.return_value = 5 mock_redis_decr_or_set.return_value = 5
client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis) client = DiscordClient(TEST_BOT_TOKEN, my_mock_redis)

View File

@@ -4,7 +4,7 @@ from urllib.parse import urlencode
from requests_oauthlib import OAuth2Session from requests_oauthlib import OAuth2Session
from requests.exceptions import HTTPError from requests.exceptions import HTTPError
from django.contrib.auth.models import User from django.contrib.auth.models import User, Group
from django.db import models from django.db import models
from django.utils.timezone import now from django.utils.timezone import now
@@ -19,7 +19,8 @@ from .app_settings import (
DISCORD_GUILD_ID, DISCORD_GUILD_ID,
DISCORD_SYNC_NAMES DISCORD_SYNC_NAMES
) )
from .discord_client import DiscordClient, DiscordApiBackoff from .discord_client import DiscordClient
from .discord_client.exceptions import DiscordClientException, DiscordApiBackoff
from .discord_client.helpers import match_or_create_roles_from_names from .discord_client.helpers import match_or_create_roles_from_names
from .utils import LoggerAddTag from .utils import LoggerAddTag
@@ -127,9 +128,17 @@ class DiscordUserManager(models.Manager):
return None return None
@staticmethod @staticmethod
def user_group_names(user: User) -> list: def user_group_names(user: User, state_name: str = None) -> list:
"""returns list of group names plus state the given user is a member of""" """returns list of group names plus state the given user is a member of"""
return [group.name for group in user.groups.all()] + [user.profile.state.name] if not state_name:
state_name = user.profile.state.name
group_names = (
[group.name for group in user.groups.all()] + [state_name]
)
logger.debug(
"Group names for roles updates of user %s are: %s", user, group_names
)
return group_names
def user_has_account(self, user: User) -> bool: def user_has_account(self, user: User) -> bool:
"""Returns True if the user has an Discord account, else False """Returns True if the user has an Discord account, else False
@@ -141,7 +150,7 @@ class DiscordUserManager(models.Manager):
return self.filter(user=user).select_related('user').exists() return self.filter(user=user).select_related('user').exists()
@classmethod @classmethod
def generate_bot_add_url(cls): def generate_bot_add_url(cls) -> str:
params = urlencode({ params = urlencode({
'client_id': DISCORD_APP_ID, 'client_id': DISCORD_APP_ID,
'scope': 'bot', 'scope': 'bot',
@@ -151,7 +160,7 @@ class DiscordUserManager(models.Manager):
return f'{DiscordClient.OAUTH_BASE_URL}?{params}' return f'{DiscordClient.OAUTH_BASE_URL}?{params}'
@classmethod @classmethod
def generate_oauth_redirect_url(cls): def generate_oauth_redirect_url(cls) -> str:
oauth = OAuth2Session( oauth = OAuth2Session(
DISCORD_APP_ID, redirect_uri=DISCORD_CALLBACK_URL, scope=cls.SCOPES DISCORD_APP_ID, redirect_uri=DISCORD_CALLBACK_URL, scope=cls.SCOPES
) )
@@ -170,11 +179,38 @@ class DiscordUserManager(models.Manager):
return token['access_token'] return token['access_token']
@classmethod @classmethod
def server_name(cls): def server_name(cls, use_cache: bool = True) -> str:
"""returns the name of the Discord server""" """returns the name of the current Discord server
return cls._bot_client().guild_name(DISCORD_GUILD_ID) or an empty string if the name could not be retrieved
Params:
- use_cache: When set False will force an API call to get the server name
"""
try:
server_name = cls._bot_client().guild_name(
guild_id=DISCORD_GUILD_ID, use_cache=use_cache
)
except (HTTPError, DiscordClientException):
server_name = ""
except Exception:
logger.warning(
"Unexpected error when trying to retrieve the server name from Discord",
exc_info=True
)
server_name = ""
return server_name
@classmethod
def group_to_role(cls, group: Group) -> dict:
"""returns the Discord role matching the given Django group by name
or an empty dict() if no matching role exist
"""
return cls._bot_client().match_role_from_name(
guild_id=DISCORD_GUILD_ID, role_name=group.name
)
@staticmethod @staticmethod
def _bot_client(is_rate_limited: bool = True): def _bot_client(is_rate_limited: bool = True) -> DiscordClient:
"""returns a bot client for access to the Discord API""" """returns a bot client for access to the Discord API"""
return DiscordClient(DISCORD_BOT_TOKEN, is_rate_limited=is_rate_limited) return DiscordClient(DISCORD_BOT_TOKEN, is_rate_limited=is_rate_limited)

Some files were not shown because too many files have changed in this diff Show More