mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-04 14:16:21 +01:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8980d8d32f | ||
|
|
9d6cf9a62e | ||
|
|
0fabb2b368 | ||
|
|
9801ca0314 | ||
|
|
fd86b26b39 | ||
|
|
b0dbef1587 | ||
|
|
a6e60bc23b | ||
|
|
137e8a876d | ||
|
|
fe9538253f | ||
|
|
edda2c248e | ||
|
|
62275639e3 | ||
|
|
d0c68b82f4 | ||
|
|
78b5953bdf | ||
|
|
25e565b099 | ||
|
|
1fe0f78ad7 | ||
|
|
fc8b68156f | ||
|
|
b47cd197ce | ||
|
|
3943426c4c | ||
|
|
08a9bd42a3 | ||
|
|
b2ff339efe | ||
|
|
c604131e04 | ||
|
|
f17607f126 | ||
|
|
94e455a57b | ||
|
|
3c9149db4a | ||
|
|
96cc615c07 | ||
|
|
cd1f4a1c2b | ||
|
|
e0f99a42db | ||
|
|
3506e417d4 | ||
|
|
36197e2212 | ||
|
|
fc5f42d01e | ||
|
|
e26d3767e0 | ||
|
|
046b37c76a | ||
|
|
925ff3e116 | ||
|
|
e5ede4f7b6 | ||
|
|
ded9301527 | ||
|
|
bd1ed6ff73 | ||
|
|
feb65980d4 | ||
|
|
e81d75a782 | ||
|
|
ff305d13ae | ||
|
|
8bcbc1a779 | ||
|
|
3874aa6fee | ||
|
|
103e9f3a11 | ||
|
|
d02c25f421 | ||
|
|
228af38a4a | ||
|
|
051a48885c | ||
|
|
6bcdc6052f | ||
|
|
af3527e64f | ||
|
|
17ef3dd07a | ||
|
|
1f165ecd2a | ||
|
|
70d1d450a9 | ||
|
|
b667892698 | ||
|
|
dc11add0e9 | ||
|
|
cb429a0b88 | ||
|
|
b51039cfc0 | ||
|
|
eadd959d95 | ||
|
|
1856e03d88 | ||
|
|
7dcfa622a3 | ||
|
|
64251b9b3c | ||
|
|
6b073dd5fc | ||
|
|
0911fabfb2 | ||
|
|
050d3f5e63 | ||
|
|
bbe3f78ad1 | ||
|
|
8204c18895 | ||
|
|
b91c788897 | ||
|
|
1d20a3029f | ||
|
|
9cfebc9ae3 | ||
|
|
ddabb4539b | ||
|
|
ada35e221b | ||
|
|
6fef9d904e | ||
|
|
67cf2b5904 | ||
|
|
3bebe792f6 | ||
|
|
00b4d89181 | ||
|
|
f729c6b650 | ||
|
|
df95f8c3f3 | ||
|
|
fe36e57d72 | ||
|
|
31197812b6 | ||
|
|
bd3fe01a12 | ||
|
|
39f7f32b7d | ||
|
|
b4522a1277 | ||
|
|
bb6a7e8327 | ||
|
|
9bd42a7579 | ||
|
|
b41430e5a3 | ||
|
|
595353e838 | ||
|
|
f1a21bb856 | ||
|
|
e44c2935f9 | ||
|
|
4d546f948d | ||
|
|
3bab349d7b | ||
|
|
eef6126ef8 | ||
|
|
5c7478fa39 | ||
|
|
64b72d0b06 | ||
|
|
b266a98b25 | ||
|
|
8a27de5df8 | ||
|
|
f9b5310fce | ||
|
|
fdce173969 | ||
|
|
7b9ddf90c1 | ||
|
|
580c8c19de | ||
|
|
55cc77140e | ||
|
|
93c89dd7cc | ||
|
|
c970cbbd2d |
@@ -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
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|
||||||
|
|||||||
@@ -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.2'
|
__version__ = '2.8.0'
|
||||||
__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__)
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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')),
|
||||||
]
|
]
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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' %}
|
||||||
|
|||||||
149
allianceauth/authentication/tests/test_backend.py
Normal file
149
allianceauth/authentication/tests/test_backend.py
Normal 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'))
|
||||||
35
allianceauth/authentication/tests/test_commands.py
Normal file
35
allianceauth/authentication/tests/test_commands.py
Normal 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())
|
||||||
68
allianceauth/authentication/tests/test_decorators.py
Normal file
68
allianceauth/authentication/tests/test_decorators.py
Normal 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)
|
||||||
@@ -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):
|
||||||
@@ -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())
|
|
||||||
@@ -83,9 +83,8 @@ class TestStatusOverviewTag(TestCase):
|
|||||||
}
|
}
|
||||||
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,
|
||||||
@@ -128,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):
|
||||||
|
|
||||||
@@ -170,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):
|
||||||
|
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
|||||||
@@ -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='78910',
|
executor_corp_id=5,
|
||||||
|
)
|
||||||
|
EveCharacter.objects.create(
|
||||||
|
character_id=1,
|
||||||
|
character_name='character.name1',
|
||||||
|
corporation_id=2345,
|
||||||
|
corporation_name='character.corp.name',
|
||||||
|
corporation_ticker='c.c.t', # max 5 chars
|
||||||
|
alliance_id=None
|
||||||
)
|
)
|
||||||
EveCharacter.objects.create(
|
EveCharacter.objects.create(
|
||||||
character_id=1234,
|
character_id=2,
|
||||||
character_name='character.name',
|
character_name='character.name2',
|
||||||
corporation_id=2345,
|
corporation_id=9876,
|
||||||
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=3456,
|
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)
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
38
allianceauth/groupmanagement/auth_hooks.py
Normal file
38
allianceauth/groupmanagement/auth_hooks.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
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']
|
||||||
|
)
|
||||||
|
|
||||||
|
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'^group/')
|
||||||
@@ -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()
|
||||||
|
)
|
||||||
|
|||||||
@@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 %}
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<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 class="text-center">{{ entry.date|date:"Y-M-d, H:i" }}</td>
|
||||||
<td class="text-center">{{ entry.requestor }}</td>
|
<td class="text-center">{{ entry.requestor }}</td>
|
||||||
<td class="text-center">{{ entry.req_char }}</td>
|
<td class="text-center">{{ entry.req_char }}</td>
|
||||||
<td class="text-center">{{ entry.req_char.corporation_name }}</td>
|
<td class="text-center">{{ entry.req_char.corporation_name }}</td>
|
||||||
@@ -66,7 +66,8 @@
|
|||||||
|
|
||||||
{% 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,7 +75,26 @@
|
|||||||
{% 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:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "allianceauth/base.html" %}
|
{% extends "allianceauth/base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load evelinks %}
|
{% load evelinks %}
|
||||||
|
|
||||||
|
|||||||
@@ -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 %}
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{% block extra_javascript %}
|
{% block extra_javascript %}
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script>
|
{% include 'bundles/clipboard-js.html' %}
|
||||||
<script>
|
<script>
|
||||||
new ClipboardJS('#clipboard-copy');
|
new ClipboardJS('#clipboard-copy');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% 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 %}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "allianceauth/base.html" %}
|
{% extends "allianceauth/base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load evelinks %}
|
{% load evelinks %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load navactive %}
|
{% load navactive %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
from django import template
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
|
|
||||||
from allianceauth.groupmanagement.managers import GroupManager
|
|
||||||
|
|
||||||
|
|
||||||
register = template.Library()
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
|
||||||
def can_manage_groups(user: User) -> bool:
|
|
||||||
"""returns True if the given user can manage groups. Returns False otherwise."""
|
|
||||||
if not isinstance(user, User):
|
|
||||||
return False
|
|
||||||
return GroupManager.can_manage_groups(user)
|
|
||||||
@@ -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
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
|
||||||
|
|
||||||
from ..templatetags.groupmanagement import can_manage_groups
|
|
||||||
|
|
||||||
MODULE_PATH = 'allianceauth.groupmanagement.templatetags.groupmanagement'
|
|
||||||
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.GroupManager.can_manage_groups')
|
|
||||||
class TestCanManageGroups(TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.user = AuthUtils.create_user('Bruce Wayne')
|
|
||||||
|
|
||||||
def test_return_normal_result(self, mock_can_manage_groups):
|
|
||||||
mock_can_manage_groups.return_value = True
|
|
||||||
|
|
||||||
self.assertTrue(can_manage_groups(self.user))
|
|
||||||
self.assertTrue(mock_can_manage_groups.called)
|
|
||||||
|
|
||||||
def test_return_false_if_not_user(self, mock_can_manage_groups):
|
|
||||||
mock_can_manage_groups.return_value = True
|
|
||||||
|
|
||||||
self.assertFalse(can_manage_groups('invalid'))
|
|
||||||
self.assertFalse(mock_can_manage_groups.called)
|
|
||||||
@@ -1,32 +1,29 @@
|
|||||||
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'),
|
url(r'^groups/', views.groups_view, name='groups'),
|
||||||
url(r'^group/', include([
|
url(r'^management/', views.group_management,
|
||||||
url(r'^management/', views.group_management,
|
name='management'),
|
||||||
name='management'),
|
url(r'^membership/$', views.group_membership,
|
||||||
url(r'^membership/$', views.group_membership,
|
name='membership'),
|
||||||
name='membership'),
|
url(r'^membership/(\w+)/$', views.group_membership_list,
|
||||||
url(r'^membership/(\w+)/$', views.group_membership_list,
|
name='membership_list'),
|
||||||
name='membership_list'),
|
url(r'^membership/(\w+)/audit/$', views.group_membership_audit, name="audit_log"),
|
||||||
url(r'^membership/(\w+)/audit/$', views.group_membership_audit, name="audit_log"),
|
url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove,
|
||||||
url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove,
|
name='membership_remove'),
|
||||||
name='membership_remove'),
|
url(r'^request_add/(\w+)', views.group_request_add,
|
||||||
url(r'^request_add/(\w+)', views.group_request_add,
|
name='request_add'),
|
||||||
name='request_add'),
|
url(r'^request/accept/(\w+)', views.group_accept_request,
|
||||||
url(r'^request/accept/(\w+)', views.group_accept_request,
|
name='accept_request'),
|
||||||
name='accept_request'),
|
url(r'^request/reject/(\w+)', views.group_reject_request,
|
||||||
url(r'^request/reject/(\w+)', views.group_reject_request,
|
name='reject_request'),
|
||||||
name='reject_request'),
|
url(r'^request_leave/(\w+)', views.group_request_leave,
|
||||||
|
name='request_leave'),
|
||||||
url(r'^request_leave/(\w+)', views.group_request_leave,
|
url(r'leave_request/accept/(\w+)', views.group_leave_accept_request,
|
||||||
name='request_leave'),
|
name='leave_accept_request'),
|
||||||
url(r'leave_request/accept/(\w+)', views.group_leave_accept_request,
|
url(r'^leave_request/reject/(\w+)', views.group_leave_reject_request,
|
||||||
name='leave_accept_request'),
|
name='leave_reject_request'),
|
||||||
url(r'^leave_request/reject/(\w+)', views.group_leave_reject_request,
|
|
||||||
name='leave_reject_request'),
|
|
||||||
])),
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
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):
|
||||||
@@ -12,6 +15,11 @@ class ApplicationsMenu(MenuItemHook):
|
|||||||
'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():
|
||||||
|
|||||||
25
allianceauth/hrapplications/managers.py
Normal file
25
allianceauth/hrapplications/managers.py
Normal 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
|
||||||
@@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "allianceauth/base.html" %}
|
{% extends "allianceauth/base.html" %}
|
||||||
{% load staticfiles %}
|
{% load static %}
|
||||||
{% load bootstrap %}
|
{% load bootstrap %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
)
|
||||||
|
|||||||
Binary file not shown.
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Binary file not shown.
@@ -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"
|
||||||
|
|||||||
BIN
allianceauth/locale/fr_FR/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/fr_FR/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2083
allianceauth/locale/fr_FR/LC_MESSAGES/django.po
Normal file
2083
allianceauth/locale/fr_FR/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
allianceauth/locale/ja/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/ja/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2057
allianceauth/locale/ja/LC_MESSAGES/django.po
Normal file
2057
allianceauth/locale/ja/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -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"
|
||||||
|
|||||||
Binary file not shown.
@@ -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"
|
||||||
|
|||||||
Binary file not shown.
@@ -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 "暗色皮肤"
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 = [
|
||||||
@@ -138,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -179,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:
|
||||||
@@ -192,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 = ''
|
||||||
@@ -229,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
|
||||||
|
|
||||||
@@ -273,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
|
||||||
|
|
||||||
@@ -280,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
|
||||||
@@ -310,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
|
||||||
@@ -540,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -280,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(
|
||||||
@@ -291,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')
|
||||||
@@ -302,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)
|
||||||
|
|
||||||
|
|
||||||
@@ -844,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,
|
||||||
@@ -896,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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -67,21 +67,25 @@ class DiscordUser(models.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{type(self).__name__}(user=\'{self.user}\', uid={self.uid})'
|
return f'{type(self).__name__}(user=\'{self.user}\', uid={self.uid})'
|
||||||
|
|
||||||
def update_nickname(self) -> bool:
|
def update_nickname(self, nickname: str = None) -> bool:
|
||||||
"""Update nickname with formatted name of main character
|
"""Update nickname with formatted name of main character
|
||||||
|
|
||||||
|
Params:
|
||||||
|
- nickname: optional nickname to be used instead of user's main
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True on success
|
- True on success
|
||||||
- None if user is no longer a member of the Discord server
|
- None if user is no longer a member of the Discord server
|
||||||
- False on error or raises exception
|
- False on error or raises exception
|
||||||
"""
|
"""
|
||||||
requested_nick = DiscordUser.objects.user_formatted_nick(self.user)
|
if not nickname:
|
||||||
if requested_nick:
|
nickname = DiscordUser.objects.user_formatted_nick(self.user)
|
||||||
|
if nickname:
|
||||||
client = DiscordUser.objects._bot_client()
|
client = DiscordUser.objects._bot_client()
|
||||||
success = client.modify_guild_member(
|
success = client.modify_guild_member(
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID,
|
||||||
user_id=self.uid,
|
user_id=self.uid,
|
||||||
nick=requested_nick
|
nick=nickname
|
||||||
)
|
)
|
||||||
if success:
|
if success:
|
||||||
logger.info('Nickname for %s has been updated', self.user)
|
logger.info('Nickname for %s has been updated', self.user)
|
||||||
@@ -92,10 +96,13 @@ class DiscordUser(models.Model):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def update_groups(self) -> bool:
|
def update_groups(self, state_name: str = None) -> bool:
|
||||||
"""update groups for a user based on his current group memberships.
|
"""update groups for a user based on his current group memberships.
|
||||||
Will add or remove roles of a user as needed.
|
Will add or remove roles of a user as needed.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
- state_name: optional state name to be used
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- True on success
|
- True on success
|
||||||
- None if user is no longer a member of the Discord server
|
- None if user is no longer a member of the Discord server
|
||||||
@@ -128,7 +135,9 @@ class DiscordUser(models.Model):
|
|||||||
requested_roles = match_or_create_roles_from_names(
|
requested_roles = match_or_create_roles_from_names(
|
||||||
client=client,
|
client=client,
|
||||||
guild_id=DISCORD_GUILD_ID,
|
guild_id=DISCORD_GUILD_ID,
|
||||||
role_names=DiscordUser.objects.user_group_names(self.user)
|
role_names=DiscordUser.objects.user_group_names(
|
||||||
|
user=self.user, state_name=state_name
|
||||||
|
)
|
||||||
)
|
)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Requested roles for user %s: %s', self.user, requested_roles.ids()
|
'Requested roles for user %s: %s', self.user, requested_roles.ids()
|
||||||
@@ -144,13 +153,13 @@ class DiscordUser(models.Model):
|
|||||||
role_ids=list(new_roles.ids())
|
role_ids=list(new_roles.ids())
|
||||||
)
|
)
|
||||||
if success:
|
if success:
|
||||||
logger.info('Groups for %s have been updated', self.user)
|
logger.info('Roles for %s have been updated', self.user)
|
||||||
else:
|
else:
|
||||||
logger.warning('Failed to update groups for %s', self.user)
|
logger.warning('Failed to update roles for %s', self.user)
|
||||||
return success
|
return success
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.info('No need to update groups for user %s', self.user)
|
logger.info('No need to update roles for user %s', self.user)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_username(self) -> bool:
|
def update_username(self) -> bool:
|
||||||
@@ -202,6 +211,7 @@ class DiscordUser(models.Model):
|
|||||||
Return None if user does no longer exist
|
Return None if user does no longer exist
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
_user = self.user
|
||||||
client = DiscordUser.objects._bot_client(is_rate_limited=is_rate_limited)
|
client = DiscordUser.objects._bot_client(is_rate_limited=is_rate_limited)
|
||||||
success = client.remove_guild_member(
|
success = client.remove_guild_member(
|
||||||
guild_id=DISCORD_GUILD_ID, user_id=self.uid
|
guild_id=DISCORD_GUILD_ID, user_id=self.uid
|
||||||
@@ -211,31 +221,31 @@ class DiscordUser(models.Model):
|
|||||||
if deleted_count > 0:
|
if deleted_count > 0:
|
||||||
if notify_user:
|
if notify_user:
|
||||||
notify(
|
notify(
|
||||||
user=self.user,
|
user=_user,
|
||||||
title=gettext_lazy('Discord Account Disabled'),
|
title=gettext_lazy('Discord Account Disabled'),
|
||||||
message=gettext_lazy(
|
message=gettext_lazy(
|
||||||
'Your Discord account was disabeled automatically '
|
'Your Discord account was disabled automatically '
|
||||||
'by Auth. If you think this was a mistake, '
|
'by Auth. If you think this was a mistake, '
|
||||||
'please contact an admin.'
|
'please contact an admin.'
|
||||||
),
|
),
|
||||||
level='warning'
|
level='warning'
|
||||||
)
|
)
|
||||||
logger.info('Account for user %s was deleted.', self.user)
|
logger.info('Account for user %s was deleted.', _user)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.debug('Account for user %s was already deleted.', self.user)
|
logger.debug('Account for user %s was already deleted.', _user)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'Failed to remove user %s from the Discord server', self.user
|
'Failed to remove user %s from the Discord server', _user
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
||||||
if handle_api_exceptions:
|
if handle_api_exceptions:
|
||||||
logger.exception(
|
logger.exception(
|
||||||
'Failed to remove user %s from Discord server: %s', self.user, ex
|
'Failed to remove user %s from Discord server: %s',self.user, ex
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from celery import shared_task, chain
|
from celery import shared_task, chain
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
@@ -26,25 +27,27 @@ BULK_TASK_PRIORITY = 6
|
|||||||
@shared_task(
|
@shared_task(
|
||||||
bind=True, name='discord.update_groups', base=QueueOnce, max_retries=None
|
bind=True, name='discord.update_groups', base=QueueOnce, max_retries=None
|
||||||
)
|
)
|
||||||
def update_groups(self, user_pk: int) -> None:
|
def update_groups(self, user_pk: int, state_name: str = None) -> None:
|
||||||
"""Update roles on Discord for given user according to his current groups
|
"""Update roles on Discord for given user according to his current groups
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- user_pk: PK of given user
|
- user_pk: PK of given user
|
||||||
"""
|
- state_name: optional state name to be used
|
||||||
_task_perform_user_action(self, user_pk, 'update_groups')
|
"""
|
||||||
|
_task_perform_user_action(self, user_pk, 'update_groups', state_name=state_name)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(
|
@shared_task(
|
||||||
bind=True, name='discord.update_nickname', base=QueueOnce, max_retries=None
|
bind=True, name='discord.update_nickname', base=QueueOnce, max_retries=None
|
||||||
)
|
)
|
||||||
def update_nickname(self, user_pk: int) -> None:
|
def update_nickname(self, user_pk: int, nickname: str = None) -> None:
|
||||||
"""Set nickname on Discord for given user to his main character name
|
"""Set nickname on Discord for given user to his main character name
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
- user_pk: PK of given user
|
- user_pk: PK of given user
|
||||||
|
- nickname: optional nickname to be used instead of user's main
|
||||||
"""
|
"""
|
||||||
_task_perform_user_action(self, user_pk, 'update_nickname')
|
_task_perform_user_action(self, user_pk, 'update_nickname', nickname=nickname)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(
|
@shared_task(
|
||||||
@@ -75,6 +78,7 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
|
|||||||
"""perform a user related action incl. managing all exceptions"""
|
"""perform a user related action incl. managing all exceptions"""
|
||||||
logger.debug("Starting %s for user with pk %s", method, user_pk)
|
logger.debug("Starting %s for user with pk %s", method, user_pk)
|
||||||
user = User.objects.get(pk=user_pk)
|
user = User.objects.get(pk=user_pk)
|
||||||
|
# logger.debug("user %s has state %s", user, user.profile.state)
|
||||||
if DiscordUser.objects.user_has_account(user):
|
if DiscordUser.objects.user_has_account(user):
|
||||||
logger.info("Running %s for user %s", method, user)
|
logger.info("Running %s for user %s", method, user)
|
||||||
try:
|
try:
|
||||||
@@ -91,7 +95,7 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
|
|||||||
raise self.retry(countdown=bo.retry_after_seconds)
|
raise self.retry(countdown=bo.retry_after_seconds)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ValueError(f'{method} not a valid method for DiscordUser: %r')
|
raise ValueError(f'{method} not a valid method for DiscordUser')
|
||||||
|
|
||||||
except (HTTPError, ConnectionError):
|
except (HTTPError, ConnectionError):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
@@ -112,7 +116,7 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
|
|||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error(
|
logger.error(
|
||||||
'%s for %s failed due to unexpected exception',
|
'%s for user %s failed due to unexpected exception',
|
||||||
method,
|
method,
|
||||||
user,
|
user,
|
||||||
exc_info=True
|
exc_info=True
|
||||||
@@ -183,9 +187,58 @@ def _bulk_update_nicknames_for_users(discord_users_qs: QuerySet) -> None:
|
|||||||
chain(update_nicknames_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
chain(update_nicknames_chain).apply_async(priority=BULK_TASK_PRIORITY)
|
||||||
|
|
||||||
|
|
||||||
|
def _task_perform_users_action(self, method: str, **kwargs) -> Any:
|
||||||
|
"""Perform an action that concerns a group of users or the whole server
|
||||||
|
and that hits the API
|
||||||
|
"""
|
||||||
|
result = None
|
||||||
|
try:
|
||||||
|
result = getattr(DiscordUser.objects, method)(**kwargs)
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
raise ValueError(f'{method} not a valid method for DiscordUser.objects')
|
||||||
|
|
||||||
|
except DiscordApiBackoff as bo:
|
||||||
|
logger.info(
|
||||||
|
"API back off for %s due to %r, retrying in %s seconds",
|
||||||
|
method,
|
||||||
|
bo,
|
||||||
|
bo.retry_after_seconds
|
||||||
|
)
|
||||||
|
raise self.retry(countdown=bo.retry_after_seconds)
|
||||||
|
|
||||||
|
except (HTTPError, ConnectionError):
|
||||||
|
logger.warning(
|
||||||
|
'%s failed, retrying in %d secs',
|
||||||
|
method,
|
||||||
|
DISCORD_TASKS_RETRY_PAUSE,
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
|
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
|
||||||
|
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
|
||||||
|
else:
|
||||||
|
logger.error('%s failed after max retries', method, exc_info=True)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
logger.error('%s failed due to unexpected exception', method, exc_info=True)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(
|
||||||
|
bind=True, name='discord.update_servername', base=QueueOnce, max_retries=None
|
||||||
|
)
|
||||||
|
def update_servername(self) -> None:
|
||||||
|
"""Updates the Discord server name"""
|
||||||
|
_task_perform_users_action(self, method="server_name", use_cache=False)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name='discord.update_all_usernames')
|
@shared_task(name='discord.update_all_usernames')
|
||||||
def update_all_usernames() -> None:
|
def update_all_usernames() -> None:
|
||||||
"""Update all usernames for all known users with a Discord account."""
|
"""Update all usernames for all known users with a Discord account.
|
||||||
|
Also updates the server name
|
||||||
|
"""
|
||||||
|
update_servername.delay()
|
||||||
discord_users_qs = DiscordUser.objects.all()
|
discord_users_qs = DiscordUser.objects.all()
|
||||||
_bulk_update_usernames_for_users(discord_users_qs)
|
_bulk_update_usernames_for_users(discord_users_qs)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<div class="text-center" style="padding-top:5px;">
|
<div class="text-center" style="padding-top:5px;">
|
||||||
<a type="button" class="btn btn-default" href="{% url 'discord:add_bot' %}">
|
<a type="button" id="btnLinkDiscordServer" class="btn btn-default" href="{% url 'discord:add_bot' %}">
|
||||||
{% trans "Link Discord Server" %}
|
{% trans "Link Discord Server" %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from ..discord_client.tests import ( # noqa
|
|||||||
ROLE_BRAVO,
|
ROLE_BRAVO,
|
||||||
ROLE_CHARLIE,
|
ROLE_CHARLIE,
|
||||||
ROLE_MIKE,
|
ROLE_MIKE,
|
||||||
|
ALL_ROLES,
|
||||||
create_user_info
|
create_user_info
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from unittest.mock import patch
|
|||||||
from django.test import TestCase, RequestFactory
|
from django.test import TestCase, RequestFactory
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
|
from allianceauth.notifications.models import Notification
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
from . import TEST_USER_NAME, TEST_USER_ID, add_permissions_to_members, MODULE_PATH
|
from . import TEST_USER_NAME, TEST_USER_ID, add_permissions_to_members, MODULE_PATH
|
||||||
@@ -30,6 +31,7 @@ class TestDiscordService(TestCase):
|
|||||||
self.service = DiscordService
|
self.service = DiscordService
|
||||||
add_permissions_to_members()
|
add_permissions_to_members()
|
||||||
self.factory = RequestFactory()
|
self.factory = RequestFactory()
|
||||||
|
Notification.objects.all().delete()
|
||||||
|
|
||||||
def test_service_enabled(self):
|
def test_service_enabled(self):
|
||||||
service = self.service()
|
service = self.service()
|
||||||
@@ -89,16 +91,17 @@ class TestDiscordService(TestCase):
|
|||||||
service = self.service()
|
service = self.service()
|
||||||
service.sync_nicknames_bulk([self.member])
|
service.sync_nicknames_bulk([self.member])
|
||||||
self.assertTrue(mock_update_nicknames_bulk.delay.called)
|
self.assertTrue(mock_update_nicknames_bulk.delay.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
def test_delete_user_is_member(self, mock_DiscordClient):
|
def test_delete_user_is_member(self, mock_DiscordClient):
|
||||||
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
mock_DiscordClient.return_value.remove_guild_member.return_value = True
|
||||||
|
|
||||||
service = self.service()
|
service = self.service()
|
||||||
service.delete_user(self.member)
|
service.delete_user(self.member, notify_user=True)
|
||||||
|
|
||||||
self.assertTrue(mock_DiscordClient.return_value.remove_guild_member.called)
|
self.assertTrue(mock_DiscordClient.return_value.remove_guild_member.called)
|
||||||
self.assertFalse(DiscordUser.objects.filter(user=self.member).exists())
|
self.assertFalse(DiscordUser.objects.filter(user=self.member).exists())
|
||||||
|
self.assertTrue(Notification.objects.filter(user=self.member).exists())
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
def test_delete_user_is_not_member(self, mock_DiscordClient):
|
def test_delete_user_is_not_member(self, mock_DiscordClient):
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ import requests_mock
|
|||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from django.core.cache import caches
|
from django.core.cache import caches
|
||||||
from django.shortcuts import reverse
|
from django.shortcuts import reverse
|
||||||
from django.test import TransactionTestCase
|
from django.test import TransactionTestCase, TestCase
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
|
from allianceauth.authentication.models import State
|
||||||
|
from allianceauth.eveonline.models import EveCharacter
|
||||||
|
from allianceauth.notifications.models import Notification
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
@@ -38,11 +41,14 @@ from . import (
|
|||||||
create_user_info
|
create_user_info
|
||||||
)
|
)
|
||||||
from ..discord_client.app_settings import DISCORD_API_BASE_URL
|
from ..discord_client.app_settings import DISCORD_API_BASE_URL
|
||||||
|
from ..discord_client.exceptions import DiscordApiBackoff
|
||||||
from ..models import DiscordUser
|
from ..models import DiscordUser
|
||||||
|
from .. import tasks
|
||||||
|
|
||||||
logger = logging.getLogger('allianceauth')
|
logger = logging.getLogger('allianceauth')
|
||||||
|
|
||||||
ROLE_MEMBER = create_role(99, 'Member')
|
ROLE_MEMBER = create_role(99, 'Member')
|
||||||
|
ROLE_BLUE = create_role(98, 'Blue')
|
||||||
|
|
||||||
# Putting all requests to Discord into objects so we can compare them better
|
# Putting all requests to Discord into objects so we can compare them better
|
||||||
DiscordRequest = namedtuple('DiscordRequest', ['method', 'url'])
|
DiscordRequest = namedtuple('DiscordRequest', ['method', 'url'])
|
||||||
@@ -87,6 +93,16 @@ def clear_cache():
|
|||||||
logger.info('Cache flushed')
|
logger.info('Cache flushed')
|
||||||
|
|
||||||
|
|
||||||
|
def reset_testdata():
|
||||||
|
AuthUtils.disconnect_signals()
|
||||||
|
Group.objects.all().delete()
|
||||||
|
User.objects.all().delete()
|
||||||
|
State.objects.all().delete()
|
||||||
|
EveCharacter.objects.all().delete()
|
||||||
|
AuthUtils.connect_signals()
|
||||||
|
Notification.objects.all().delete()
|
||||||
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
@override_settings(CELERY_ALWAYS_EAGER=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
@requests_mock.Mocker()
|
@requests_mock.Mocker()
|
||||||
@@ -96,16 +112,26 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super().setUpClass()
|
super().setUpClass()
|
||||||
cls.maxDiff = None
|
cls.maxDiff = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
"""All tests: Given a user with member state,
|
||||||
|
service permission and active Discord account
|
||||||
|
"""
|
||||||
clear_cache()
|
clear_cache()
|
||||||
AuthUtils.disconnect_signals()
|
reset_testdata()
|
||||||
Group.objects.all().delete()
|
self.group_charlie = Group.objects.create(name='charlie')
|
||||||
User.objects.all().delete()
|
|
||||||
AuthUtils.connect_signals()
|
# States
|
||||||
self.group_3 = Group.objects.create(name='charlie')
|
self.member_state = AuthUtils.get_member_state()
|
||||||
self.user = AuthUtils.create_member(TEST_USER_NAME)
|
self.guest_state = AuthUtils.get_guest_state()
|
||||||
AuthUtils.add_main_character_2(
|
self.blue_state = AuthUtils.create_state("Blue", 50)
|
||||||
|
permission = AuthUtils.get_permission_by_name('discord.access_discord')
|
||||||
|
self.member_state.permissions.add(permission)
|
||||||
|
self.blue_state.permissions.add(permission)
|
||||||
|
|
||||||
|
# Test user
|
||||||
|
self.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
|
self.main = AuthUtils.add_main_character_2(
|
||||||
self.user,
|
self.user,
|
||||||
TEST_MAIN_NAME,
|
TEST_MAIN_NAME,
|
||||||
TEST_MAIN_ID,
|
TEST_MAIN_ID,
|
||||||
@@ -113,60 +139,55 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
corp_name='test_corp',
|
corp_name='test_corp',
|
||||||
corp_ticker='TEST',
|
corp_ticker='TEST',
|
||||||
disconnect_signals=True
|
disconnect_signals=True
|
||||||
)
|
)
|
||||||
self.discord_user = DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
self.member_state.member_characters.add(self.main)
|
||||||
add_permissions_to_members()
|
|
||||||
|
|
||||||
def test_name_of_main_changes(self, requests_mocker):
|
# verify user is a member and has an account
|
||||||
# modify_guild_member()
|
self.user = User.objects.get(pk=self.user.pk)
|
||||||
|
self.assertEqual(self.user.profile.state, self.member_state)
|
||||||
|
|
||||||
|
self.discord_user = DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
|
def test_when_name_of_main_changes_then_discord_nick_is_updated(
|
||||||
|
self, requests_mocker
|
||||||
|
):
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# changing nick to trigger signals
|
# changing nick to trigger signals
|
||||||
new_nick = f'Testnick {uuid1().hex}'[:32]
|
new_nick = f'Testnick {uuid1().hex}'[:32]
|
||||||
self.user.profile.main_character.character_name = new_nick
|
self.user.profile.main_character.character_name = new_nick
|
||||||
self.user.profile.main_character.save()
|
self.user.profile.main_character.save()
|
||||||
|
|
||||||
# Need to have called modify_guild_member two times only
|
# verify Discord nick was updates
|
||||||
# Once for sync nickname
|
nick_updated = False
|
||||||
# Once for change of main character
|
|
||||||
requests_made = list()
|
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
requests_made.append(DiscordRequest(r.method, r.url))
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
|
if my_request == modify_guild_member_request and "nick" in r.json():
|
||||||
|
nick_updated = True
|
||||||
|
self.assertEqual(r.json()["nick"], new_nick)
|
||||||
|
|
||||||
|
self.assertTrue(nick_updated)
|
||||||
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
expected = [modify_guild_member_request, modify_guild_member_request]
|
def test_when_name_of_main_changes_and_user_deleted_then_account_is_deleted(
|
||||||
self.assertListEqual(requests_made, expected)
|
self, requests_mocker
|
||||||
|
):
|
||||||
def test_name_of_main_changes_but_user_deleted(self, requests_mocker):
|
|
||||||
# modify_guild_member()
|
|
||||||
requests_mocker.patch(
|
requests_mocker.patch(
|
||||||
modify_guild_member_request.url, status_code=404, json={'code': 10007}
|
modify_guild_member_request.url, status_code=404, json={'code': 10007}
|
||||||
)
|
)
|
||||||
# remove_guild_member()
|
|
||||||
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# changing nick to trigger signals
|
# changing nick to trigger signals
|
||||||
new_nick = f'Testnick {uuid1().hex}'[:32]
|
new_nick = f'Testnick {uuid1().hex}'[:32]
|
||||||
self.user.profile.main_character.character_name = new_nick
|
self.user.profile.main_character.character_name = new_nick
|
||||||
self.user.profile.main_character.save()
|
self.user.profile.main_character.save()
|
||||||
|
|
||||||
|
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
# Need to have called modify_guild_member two times only
|
def test_when_name_of_main_changes_and_and_rate_limited_then_dont_call_api(
|
||||||
# Once for sync nickname
|
|
||||||
# Once for change of main character
|
|
||||||
requests_made = list()
|
|
||||||
for r in requests_mocker.request_history:
|
|
||||||
requests_made.append(DiscordRequest(r.method, r.url))
|
|
||||||
|
|
||||||
expected = [
|
|
||||||
modify_guild_member_request,
|
|
||||||
remove_guild_member_request,
|
|
||||||
]
|
|
||||||
self.assertListEqual(requests_made, expected)
|
|
||||||
# self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
|
||||||
|
|
||||||
def test_name_of_main_changes_but_user_rate_limited(
|
|
||||||
self, requests_mocker
|
self, requests_mocker
|
||||||
):
|
):
|
||||||
# modify_guild_member()
|
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# exhausting rate limit
|
# exhausting rate limit
|
||||||
@@ -183,98 +204,232 @@ class TestServiceFeatures(TransactionTestCase):
|
|||||||
self.user.profile.main_character.save()
|
self.user.profile.main_character.save()
|
||||||
|
|
||||||
# should not have called the API
|
# should not have called the API
|
||||||
requests_made = list()
|
requests_made = [
|
||||||
for r in requests_mocker.request_history:
|
DiscordRequest(r.method, r.url) for r in requests_mocker.request_history
|
||||||
requests_made.append(DiscordRequest(r.method, r.url))
|
]
|
||||||
|
|
||||||
|
self.assertListEqual(requests_made, list())
|
||||||
|
|
||||||
expected = list()
|
def test_when_member_is_demoted_to_guest_then_his_account_is_deleted(
|
||||||
self.assertListEqual(requests_made, expected)
|
self, requests_mocker
|
||||||
|
):
|
||||||
def test_user_demoted_to_guest(self, requests_mocker):
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
# remove_guild_member()
|
|
||||||
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
||||||
self.user.groups.clear()
|
|
||||||
|
# our user is a member and has an account
|
||||||
requests_made = list()
|
self.assertTrue(self.user.has_perm('discord.access_discord'))
|
||||||
for r in requests_mocker.request_history:
|
|
||||||
requests_made.append(DiscordRequest(r.method, r.url))
|
# now we demote him to guest
|
||||||
|
self.member_state.member_characters.remove(self.main)
|
||||||
|
|
||||||
# compare the list of made requests with expected
|
# verify user is now guest
|
||||||
expected = [remove_guild_member_request]
|
self.user = User.objects.get(pk=self.user.pk)
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertEqual(self.user.profile.state, AuthUtils.get_guest_state())
|
||||||
|
|
||||||
|
# verify user has no longer access to Discord and no account
|
||||||
|
self.assertFalse(self.user.has_perm('discord.access_discord'))
|
||||||
|
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
|
# verify account was actually deleted from Discord server
|
||||||
|
requests_made = [
|
||||||
|
DiscordRequest(r.method, r.url) for r in requests_mocker.request_history
|
||||||
|
]
|
||||||
|
self.assertIn(remove_guild_member_request, requests_made)
|
||||||
|
|
||||||
|
# verify user has been notified
|
||||||
|
self.assertTrue(Notification.objects.filter(user=self.user).exists())
|
||||||
|
|
||||||
|
def test_when_member_changes_to_blue_state_then_roles_are_updated_accordingly(
|
||||||
|
self, requests_mocker
|
||||||
|
):
|
||||||
|
# request mocks
|
||||||
|
requests_mocker.get(
|
||||||
|
guild_member_request.url,
|
||||||
|
json={'user': create_user_info(), 'roles': ['3', '13', '99']}
|
||||||
|
)
|
||||||
|
requests_mocker.get(
|
||||||
|
guild_roles_request.url,
|
||||||
|
json=[
|
||||||
|
ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER, ROLE_BLUE
|
||||||
|
]
|
||||||
|
)
|
||||||
|
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
||||||
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
|
AuthUtils.disconnect_signals()
|
||||||
|
self.user.groups.add(self.group_charlie)
|
||||||
|
AuthUtils.connect_signals()
|
||||||
|
|
||||||
def test_adding_group_to_user_role_exists(self, requests_mocker):
|
# demote user to blue state
|
||||||
# guild_member()
|
self.blue_state.member_characters.add(self.main)
|
||||||
|
self.member_state.member_characters.remove(self.main)
|
||||||
|
|
||||||
|
# verify roles for user where updated
|
||||||
|
roles_updated = False
|
||||||
|
for r in requests_mocker.request_history:
|
||||||
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
|
if my_request == modify_guild_member_request and "roles" in r.json():
|
||||||
|
roles_updated = True
|
||||||
|
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 98})
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertTrue(roles_updated)
|
||||||
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
|
def test_when_group_added_to_member_and_role_known_then_his_roles_are_updated(
|
||||||
|
self, requests_mocker
|
||||||
|
):
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_member_request.url,
|
guild_member_request.url,
|
||||||
json={
|
json={
|
||||||
'user': create_user_info(),
|
'user': create_user_info(),
|
||||||
'roles': ['1', '13', '99']
|
'roles': ['13', '99']
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# guild_roles()
|
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_CHARLIE, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
# create_guild_role()
|
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
||||||
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
|
||||||
# modify_guild_member()
|
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# adding new group to trigger signals
|
# adding new group to trigger signals
|
||||||
self.user.groups.add(self.group_3)
|
self.user.groups.add(self.group_charlie)
|
||||||
self.user.refresh_from_db()
|
|
||||||
|
# verify roles for user where updated
|
||||||
# compare the list of made requests with expected
|
roles_updated = False
|
||||||
requests_made = list()
|
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
requests_made.append(DiscordRequest(r.method, r.url))
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
|
if my_request == modify_guild_member_request and "roles" in r.json():
|
||||||
|
roles_updated = True
|
||||||
|
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 99})
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertTrue(roles_updated)
|
||||||
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
|
|
||||||
expected = [
|
def test_when_group_added_to_member_and_role_unknown_then_his_roles_are_updated(
|
||||||
guild_member_request,
|
self, requests_mocker
|
||||||
guild_roles_request,
|
):
|
||||||
modify_guild_member_request
|
|
||||||
]
|
|
||||||
self.assertListEqual(requests_made, expected)
|
|
||||||
|
|
||||||
def test_adding_group_to_user_role_does_not_exist(self, requests_mocker):
|
|
||||||
# guild_member()
|
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_member_request.url,
|
guild_member_request.url,
|
||||||
json={
|
json={
|
||||||
'user': {'id': str(TEST_USER_ID), 'username': TEST_MAIN_NAME},
|
'user': {'id': str(TEST_USER_ID), 'username': TEST_MAIN_NAME},
|
||||||
'roles': ['1', '13', '99']
|
'roles': ['13', '99']
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# guild_roles()
|
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
# create_guild_role()
|
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
||||||
requests_mocker.post(create_guild_role_request.url, json=ROLE_CHARLIE)
|
|
||||||
# modify_guild_member()
|
|
||||||
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
requests_mocker.patch(modify_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# adding new group to trigger signals
|
# adding new group to trigger signals
|
||||||
self.user.groups.add(self.group_3)
|
self.user.groups.add(self.group_charlie)
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
|
|
||||||
# compare the list of made requests with expected
|
# verify roles for user where updated
|
||||||
requests_made = list()
|
roles_updated = False
|
||||||
for r in requests_mocker.request_history:
|
for r in requests_mocker.request_history:
|
||||||
requests_made.append(DiscordRequest(r.method, r.url))
|
my_request = DiscordRequest(r.method, r.url)
|
||||||
|
if my_request == modify_guild_member_request and "roles" in r.json():
|
||||||
expected = [
|
roles_updated = True
|
||||||
guild_member_request,
|
self.assertSetEqual(set(r.json()["roles"]), {3, 13, 99})
|
||||||
guild_roles_request,
|
break
|
||||||
create_guild_role_request,
|
|
||||||
modify_guild_member_request
|
self.assertTrue(roles_updated)
|
||||||
]
|
self.assertTrue(DiscordUser.objects.user_has_account(self.user))
|
||||||
self.assertListEqual(requests_made, expected)
|
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
|
@patch(MODULE_PATH + '.managers.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
|
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
|
@requests_mock.Mocker()
|
||||||
|
class StateTestCase(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
clear_cache()
|
||||||
|
reset_testdata()
|
||||||
|
|
||||||
|
self.user = AuthUtils.create_user('test_user', disconnect_signals=True)
|
||||||
|
AuthUtils.add_main_character(
|
||||||
|
self.user,
|
||||||
|
'Perm Test Character', '99',
|
||||||
|
corp_id='100',
|
||||||
|
alliance_id='200',
|
||||||
|
corp_name='Perm Test Corp',
|
||||||
|
alliance_name='Perm Test Alliance'
|
||||||
|
)
|
||||||
|
self.test_character = EveCharacter.objects.get(character_id='99')
|
||||||
|
self.member_state = State.objects.create(
|
||||||
|
name='Test Member',
|
||||||
|
priority=150,
|
||||||
|
)
|
||||||
|
self.access_discord = AuthUtils.get_permission_by_name('discord.access_discord')
|
||||||
|
self.member_state.permissions.add(self.access_discord)
|
||||||
|
self.member_state.member_characters.add(self.test_character)
|
||||||
|
|
||||||
|
def _add_discord_user(self):
|
||||||
|
self.discord_user = DiscordUser.objects.create(
|
||||||
|
user=self.user, uid="12345678910"
|
||||||
|
)
|
||||||
|
|
||||||
|
def _refresh_user(self):
|
||||||
|
self.user = User.objects.get(pk=self.user.pk)
|
||||||
|
|
||||||
|
def test_perm_changes_to_higher_priority_state_creation(self, requests_mocker):
|
||||||
|
mock_url = DiscordRequest(
|
||||||
|
method='DELETE',
|
||||||
|
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/12345678910'
|
||||||
|
)
|
||||||
|
requests_mocker.delete(mock_url.url, status_code=204)
|
||||||
|
self._add_discord_user()
|
||||||
|
self._refresh_user()
|
||||||
|
higher_state = State.objects.create(
|
||||||
|
name='Higher State',
|
||||||
|
priority=200,
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(self.user.discord)
|
||||||
|
higher_state.member_characters.add(self.test_character)
|
||||||
|
self._refresh_user()
|
||||||
|
self.assertEquals(higher_state, self.user.profile.state)
|
||||||
|
with self.assertRaises(DiscordUser.DoesNotExist):
|
||||||
|
self.user.discord
|
||||||
|
higher_state.member_characters.clear()
|
||||||
|
self._refresh_user()
|
||||||
|
self.assertEquals(self.member_state, self.user.profile.state)
|
||||||
|
with self.assertRaises(DiscordUser.DoesNotExist):
|
||||||
|
self.user.discord
|
||||||
|
|
||||||
|
def test_perm_changes_to_lower_priority_state_creation(self, requests_mocker):
|
||||||
|
mock_url = DiscordRequest(
|
||||||
|
method='DELETE',
|
||||||
|
url=f'{DISCORD_API_BASE_URL}guilds/{TEST_GUILD_ID}/members/12345678910'
|
||||||
|
)
|
||||||
|
requests_mocker.delete(mock_url.url, status_code=204)
|
||||||
|
self._add_discord_user()
|
||||||
|
self._refresh_user()
|
||||||
|
lower_state = State.objects.create(
|
||||||
|
name='Lower State',
|
||||||
|
priority=125,
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(self.user.discord)
|
||||||
|
lower_state.member_characters.add(self.test_character)
|
||||||
|
self._refresh_user()
|
||||||
|
self.assertEquals(self.member_state, self.user.profile.state)
|
||||||
|
self.member_state.member_characters.clear()
|
||||||
|
self._refresh_user()
|
||||||
|
self.assertEquals(lower_state, self.user.profile.state)
|
||||||
|
with self.assertRaises(DiscordUser.DoesNotExist):
|
||||||
|
self.user.discord
|
||||||
|
self.member_state.member_characters.add(self.test_character)
|
||||||
|
self._refresh_user()
|
||||||
|
self.assertEquals(self.member_state, self.user.profile.state)
|
||||||
|
with self.assertRaises(DiscordUser.DoesNotExist):
|
||||||
|
self.user.discord
|
||||||
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.managers.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
@patch(MODULE_PATH + '.managers.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
@patch(MODULE_PATH + '.models.DISCORD_GUILD_ID', TEST_GUILD_ID)
|
||||||
@requests_mock.Mocker()
|
@requests_mock.Mocker()
|
||||||
@@ -282,6 +437,7 @@ class TestUserFeatures(WebTest):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
clear_cache()
|
clear_cache()
|
||||||
|
reset_testdata()
|
||||||
self.member = AuthUtils.create_member(TEST_USER_NAME)
|
self.member = AuthUtils.create_member(TEST_USER_NAME)
|
||||||
AuthUtils.add_main_character_2(
|
AuthUtils.add_main_character_2(
|
||||||
self.member,
|
self.member,
|
||||||
@@ -290,25 +446,26 @@ class TestUserFeatures(WebTest):
|
|||||||
disconnect_signals=True
|
disconnect_signals=True
|
||||||
)
|
)
|
||||||
add_permissions_to_members()
|
add_permissions_to_members()
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
@patch(MODULE_PATH + '.managers.OAuth2Session')
|
@patch(MODULE_PATH + '.managers.OAuth2Session')
|
||||||
def test_user_activation_normal(
|
def test_user_activation_normal(
|
||||||
self, requests_mocker, mock_OAuth2Session, mock_messages
|
self, requests_mocker, mock_OAuth2Session, mock_messages
|
||||||
):
|
):
|
||||||
# user_get_current()
|
# setup
|
||||||
|
requests_mocker.get(
|
||||||
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
user_get_current_request.url,
|
user_get_current_request.url,
|
||||||
json=create_user_info(
|
json=create_user_info(
|
||||||
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# guild_roles()
|
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
# add_guild_member()
|
|
||||||
requests_mocker.put(add_guild_member_request.url, status_code=201)
|
requests_mocker.put(add_guild_member_request.url, status_code=201)
|
||||||
|
|
||||||
authentication_code = 'auth_code'
|
authentication_code = 'auth_code'
|
||||||
@@ -320,8 +477,12 @@ class TestUserFeatures(WebTest):
|
|||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# click activate on the service page
|
# user opens services page
|
||||||
response = self.app.get(reverse('discord:activate'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
|
# user clicks Discord service activation link on page
|
||||||
|
response = services_page.click(href=reverse('discord:activate'))
|
||||||
|
|
||||||
# check we got a redirect to Discord OAuth
|
# check we got a redirect to Discord OAuth
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
@@ -343,7 +504,10 @@ class TestUserFeatures(WebTest):
|
|||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
user_get_current_request, guild_roles_request, add_guild_member_request
|
guild_infos_request,
|
||||||
|
user_get_current_request,
|
||||||
|
guild_roles_request,
|
||||||
|
add_guild_member_request
|
||||||
]
|
]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@@ -352,19 +516,21 @@ class TestUserFeatures(WebTest):
|
|||||||
def test_user_activation_failed(
|
def test_user_activation_failed(
|
||||||
self, requests_mocker, mock_OAuth2Session, mock_messages
|
self, requests_mocker, mock_OAuth2Session, mock_messages
|
||||||
):
|
):
|
||||||
# user_get_current()
|
# setup
|
||||||
|
requests_mocker.get(
|
||||||
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
|
)
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
user_get_current_request.url,
|
user_get_current_request.url,
|
||||||
json=create_user_info(
|
json=create_user_info(
|
||||||
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
TEST_USER_ID, TEST_USER_NAME, TEST_USER_DISCRIMINATOR
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# guild_roles()
|
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_roles_request.url,
|
guild_roles_request.url,
|
||||||
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
json=[ROLE_ALPHA, ROLE_BRAVO, ROLE_MIKE, ROLE_MEMBER]
|
||||||
)
|
)
|
||||||
# add_guild_member()
|
|
||||||
mock_exception = HTTPError('error')
|
mock_exception = HTTPError('error')
|
||||||
mock_exception.response = Mock()
|
mock_exception.response = Mock()
|
||||||
mock_exception.response.status_code = 503
|
mock_exception.response.status_code = 503
|
||||||
@@ -378,9 +544,13 @@ class TestUserFeatures(WebTest):
|
|||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
|
# user opens services page
|
||||||
|
services_page = self.app.get(reverse('services:services'))
|
||||||
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
# click activate on the service page
|
# click activate on the service page
|
||||||
response = self.app.get(reverse('discord:activate'))
|
response = services_page.click(href=reverse('discord:activate'))
|
||||||
|
|
||||||
# check we got a redirect to Discord OAuth
|
# check we got a redirect to Discord OAuth
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
@@ -402,27 +572,31 @@ class TestUserFeatures(WebTest):
|
|||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
user_get_current_request, guild_roles_request, add_guild_member_request
|
guild_infos_request,
|
||||||
|
user_get_current_request,
|
||||||
|
guild_roles_request,
|
||||||
|
add_guild_member_request
|
||||||
]
|
]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
def test_user_deactivation_normal(self, requests_mocker, mock_messages):
|
def test_user_deactivation_normal(self, requests_mocker, mock_messages):
|
||||||
# guild_infos()
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'})
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
|
)
|
||||||
# remove_guild_member()
|
|
||||||
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
requests_mocker.delete(remove_guild_member_request.url, status_code=204)
|
||||||
|
|
||||||
# user needs have an account
|
|
||||||
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# click deactivate on the service page
|
# user opens services page
|
||||||
response = self.app.get(reverse('discord:deactivate'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
|
# click deactivate on the service page
|
||||||
|
response = services_page.click(href=reverse('discord:deactivate'))
|
||||||
|
|
||||||
# check we got a redirect to service page
|
# check we got a redirect to service page
|
||||||
self.assertRedirects(response, expected_url=reverse('services:services'))
|
self.assertRedirects(response, expected_url=reverse('services:services'))
|
||||||
@@ -436,29 +610,31 @@ class TestUserFeatures(WebTest):
|
|||||||
obj = DiscordRequest(r.method, r.url)
|
obj = DiscordRequest(r.method, r.url)
|
||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [remove_guild_member_request, guild_infos_request]
|
expected = [guild_infos_request, remove_guild_member_request]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.views.messages')
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
def test_user_deactivation_fails(self, requests_mocker, mock_messages):
|
def test_user_deactivation_fails(self, requests_mocker, mock_messages):
|
||||||
# guild_infos()
|
# setup
|
||||||
requests_mocker.get(
|
requests_mocker.get(
|
||||||
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'})
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
|
)
|
||||||
# remove_guild_member()
|
|
||||||
mock_exception = HTTPError('error')
|
mock_exception = HTTPError('error')
|
||||||
mock_exception.response = Mock()
|
mock_exception.response = Mock()
|
||||||
mock_exception.response.status_code = 503
|
mock_exception.response.status_code = 503
|
||||||
requests_mocker.delete(remove_guild_member_request.url, exc=mock_exception)
|
requests_mocker.delete(remove_guild_member_request.url, exc=mock_exception)
|
||||||
|
|
||||||
# user needs have an account
|
|
||||||
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.member, uid=TEST_USER_ID)
|
||||||
|
|
||||||
# login
|
# login
|
||||||
self.app.set_user(self.member)
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
# click deactivate on the service page
|
# user opens services page
|
||||||
response = self.app.get(reverse('discord:deactivate'))
|
services_page = self.app.get(reverse('services:services'))
|
||||||
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
|
# click deactivate on the service page
|
||||||
|
response = services_page.click(href=reverse('discord:deactivate'))
|
||||||
|
|
||||||
# check we got a redirect to service page
|
# check we got a redirect to service page
|
||||||
self.assertRedirects(response, expected_url=reverse('services:services'))
|
self.assertRedirects(response, expected_url=reverse('services:services'))
|
||||||
@@ -472,5 +648,60 @@ class TestUserFeatures(WebTest):
|
|||||||
obj = DiscordRequest(r.method, r.url)
|
obj = DiscordRequest(r.method, r.url)
|
||||||
requests_made.append(obj)
|
requests_made.append(obj)
|
||||||
|
|
||||||
expected = [remove_guild_member_request, guild_infos_request]
|
expected = [guild_infos_request, remove_guild_member_request]
|
||||||
self.assertListEqual(requests_made, expected)
|
self.assertListEqual(requests_made, expected)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.views.messages')
|
||||||
|
def test_user_add_new_server(self, requests_mocker, mock_messages):
|
||||||
|
# setup
|
||||||
|
mock_exception = HTTPError(Mock(**{"response.status_code": 400}))
|
||||||
|
requests_mocker.get(guild_infos_request.url, exc=mock_exception)
|
||||||
|
|
||||||
|
# login
|
||||||
|
self.member.is_superuser = True
|
||||||
|
self.member.is_staff = True
|
||||||
|
self.member.save()
|
||||||
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
|
# click deactivate on the service page
|
||||||
|
response = self.app.get(reverse('services:services'))
|
||||||
|
|
||||||
|
# check we got can see the page and the "link server" button
|
||||||
|
self.assertEqual(response.status_int, 200)
|
||||||
|
self.assertIsNotNone(response.html.find(id='btnLinkDiscordServer'))
|
||||||
|
|
||||||
|
def test_when_server_name_fails_user_can_still_see_service_page(
|
||||||
|
self, requests_mocker
|
||||||
|
):
|
||||||
|
# setup
|
||||||
|
requests_mocker.get(guild_infos_request.url, exc=DiscordApiBackoff(1000))
|
||||||
|
|
||||||
|
# login
|
||||||
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
|
# user opens services page
|
||||||
|
services_page = self.app.get(reverse('services:services'))
|
||||||
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
|
||||||
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
|
def test_server_name_is_updated_by_task(
|
||||||
|
self, requests_mocker
|
||||||
|
):
|
||||||
|
# setup
|
||||||
|
requests_mocker.get(
|
||||||
|
guild_infos_request.url, json={'id': TEST_GUILD_ID, 'name': 'Test Guild'}
|
||||||
|
)
|
||||||
|
# run task to update usernames
|
||||||
|
tasks.update_all_usernames()
|
||||||
|
|
||||||
|
# login
|
||||||
|
self.app.set_user(self.member)
|
||||||
|
|
||||||
|
# disable API call to make sure server name is not retrieved from API
|
||||||
|
mock_exception = HTTPError(Mock(**{"response.status_code": 400}))
|
||||||
|
requests_mocker.get(guild_infos_request.url, exc=mock_exception)
|
||||||
|
|
||||||
|
# user opens services page
|
||||||
|
services_page = self.app.get(reverse('services:services'))
|
||||||
|
self.assertEqual(services_page.status_code, 200)
|
||||||
|
self.assertIn("Test Guild", services_page.text)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from . import (
|
|||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
ROLE_ALPHA,
|
ROLE_ALPHA,
|
||||||
ROLE_BRAVO,
|
ROLE_BRAVO,
|
||||||
ROLE_CHARLIE
|
ROLE_CHARLIE,
|
||||||
)
|
)
|
||||||
from ..discord_client.tests import create_matched_role
|
from ..discord_client.tests import create_matched_role
|
||||||
from ..app_settings import (
|
from ..app_settings import (
|
||||||
@@ -361,3 +361,61 @@ class TestUserHasAccount(TestCase):
|
|||||||
|
|
||||||
def test_return_false_if_not_called_with_user_object(self):
|
def test_return_false_if_not_called_with_user_object(self):
|
||||||
self.assertFalse(DiscordUser.objects.user_has_account('abc'))
|
self.assertFalse(DiscordUser.objects.user_has_account('abc'))
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
|
@patch(MODULE_PATH + '.managers.logger')
|
||||||
|
class TestServerName(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
cls.user = AuthUtils.create_user(TEST_USER_NAME)
|
||||||
|
|
||||||
|
def test_returns_name_when_api_returns_it(self, mock_logger, mock_DiscordClient):
|
||||||
|
server_name = "El Dorado"
|
||||||
|
mock_DiscordClient.return_value.guild_name.return_value = server_name
|
||||||
|
|
||||||
|
self.assertEqual(DiscordUser.objects.server_name(), server_name)
|
||||||
|
self.assertFalse(mock_logger.warning.called)
|
||||||
|
|
||||||
|
def test_returns_empty_string_when_api_throws_http_error(
|
||||||
|
self, mock_logger, mock_DiscordClient
|
||||||
|
):
|
||||||
|
mock_exception = HTTPError('Test exception')
|
||||||
|
mock_exception.response = Mock(**{"status_code": 440})
|
||||||
|
mock_DiscordClient.return_value.guild_name.side_effect = mock_exception
|
||||||
|
|
||||||
|
self.assertEqual(DiscordUser.objects.server_name(), "")
|
||||||
|
self.assertFalse(mock_logger.warning.called)
|
||||||
|
|
||||||
|
def test_returns_empty_string_when_api_throws_service_error(
|
||||||
|
self, mock_logger, mock_DiscordClient
|
||||||
|
):
|
||||||
|
mock_DiscordClient.return_value.guild_name.side_effect = DiscordApiBackoff(1000)
|
||||||
|
|
||||||
|
self.assertEqual(DiscordUser.objects.server_name(), "")
|
||||||
|
self.assertFalse(mock_logger.warning.called)
|
||||||
|
|
||||||
|
def test_returns_empty_string_when_api_throws_unexpected_error(
|
||||||
|
self, mock_logger, mock_DiscordClient
|
||||||
|
):
|
||||||
|
mock_DiscordClient.return_value.guild_name.side_effect = RuntimeError
|
||||||
|
|
||||||
|
self.assertEqual(DiscordUser.objects.server_name(), "")
|
||||||
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.managers.DiscordClient', spec=DiscordClient)
|
||||||
|
class TestRoleForGroup(TestCase):
|
||||||
|
def test_return_role_if_found(self, mock_DiscordClient):
|
||||||
|
mock_DiscordClient.return_value.match_role_from_name.return_value = ROLE_ALPHA
|
||||||
|
|
||||||
|
group = Group.objects.create(name='alpha')
|
||||||
|
self.assertEqual(DiscordUser.objects.group_to_role(group), ROLE_ALPHA)
|
||||||
|
|
||||||
|
def test_return_empty_dict_if_not_found(self, mock_DiscordClient):
|
||||||
|
mock_DiscordClient.return_value.match_role_from_name.return_value = dict()
|
||||||
|
|
||||||
|
group = Group.objects.create(name='unknown')
|
||||||
|
self.assertEqual(DiscordUser.objects.group_to_role(group), dict())
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ logger = set_logger_to_file(MODULE_PATH, __file__)
|
|||||||
|
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.DiscordUser.update_groups')
|
@patch(MODULE_PATH + '.DiscordUser.update_groups')
|
||||||
|
@patch(MODULE_PATH + ".logger")
|
||||||
class TestUpdateGroups(TestCase):
|
class TestUpdateGroups(TestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -32,16 +33,18 @@ class TestUpdateGroups(TestCase):
|
|||||||
cls.group_1.user_set.add(cls.user)
|
cls.group_1.user_set.add(cls.user)
|
||||||
cls.group_2.user_set.add(cls.user)
|
cls.group_2.user_set.add(cls.user)
|
||||||
|
|
||||||
def test_can_update_groups(self, mock_update_groups):
|
def test_can_update_groups(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
self.assertTrue(mock_update_groups.called)
|
self.assertTrue(mock_update_groups.called)
|
||||||
|
|
||||||
def test_no_action_if_user_has_no_discord_account(self, mock_update_groups):
|
def test_no_action_if_user_has_no_discord_account(
|
||||||
|
self, mock_logger, mock_update_groups
|
||||||
|
):
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
self.assertFalse(mock_update_groups.called)
|
self.assertFalse(mock_update_groups.called)
|
||||||
|
|
||||||
def test_retries_on_api_backoff(self, mock_update_groups):
|
def test_retries_on_api_backoff(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_exception = DiscordApiBackoff(999)
|
mock_exception = DiscordApiBackoff(999)
|
||||||
mock_update_groups.side_effect = mock_exception
|
mock_update_groups.side_effect = mock_exception
|
||||||
@@ -49,7 +52,7 @@ class TestUpdateGroups(TestCase):
|
|||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
def test_retry_on_http_error_except_404(self, mock_update_groups):
|
def test_retry_on_http_error_except_404(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_exception = HTTPError('error')
|
mock_exception = HTTPError('error')
|
||||||
mock_exception.response = MagicMock()
|
mock_exception.response = MagicMock()
|
||||||
@@ -58,8 +61,12 @@ class TestUpdateGroups(TestCase):
|
|||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
def test_retry_on_http_error_404_when_user_not_deleted(self, mock_update_groups):
|
def test_retry_on_http_error_404_when_user_not_deleted(
|
||||||
|
self, mock_logger, mock_update_groups
|
||||||
|
):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_exception = HTTPError('error')
|
mock_exception = HTTPError('error')
|
||||||
mock_exception.response = MagicMock()
|
mock_exception.response = MagicMock()
|
||||||
@@ -68,26 +75,31 @@ class TestUpdateGroups(TestCase):
|
|||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
def test_retry_on_non_http_error(self, mock_update_groups):
|
def test_retry_on_non_http_error(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_update_groups.side_effect = ConnectionError
|
mock_update_groups.side_effect = ConnectionError
|
||||||
|
|
||||||
with self.assertRaises(Retry):
|
with self.assertRaises(Retry):
|
||||||
tasks.update_groups(self.user.pk)
|
tasks.update_groups(self.user.pk)
|
||||||
|
|
||||||
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
||||||
def test_log_error_if_retries_exhausted(self, mock_update_groups):
|
def test_log_error_if_retries_exhausted(self, mock_logger, mock_update_groups):
|
||||||
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
DiscordUser.objects.create(user=self.user, uid=TEST_USER_ID)
|
||||||
mock_task = MagicMock(**{'request.retries': 3})
|
mock_task = MagicMock(**{'request.retries': 3})
|
||||||
mock_update_groups.side_effect = ConnectionError
|
mock_update_groups.side_effect = ConnectionError
|
||||||
update_groups_inner = tasks.update_groups.__wrapped__.__func__
|
update_groups_inner = tasks.update_groups.__wrapped__.__func__
|
||||||
|
|
||||||
update_groups_inner(mock_task, self.user.pk)
|
update_groups_inner(mock_task, self.user.pk)
|
||||||
|
self.assertTrue(mock_logger.error.called)
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.delete_user.delay')
|
@patch(MODULE_PATH + '.delete_user.delay')
|
||||||
def test_delete_user_if_user_is_no_longer_member_of_discord_server(
|
def test_delete_user_if_user_is_no_longer_member_of_discord_server(
|
||||||
self, mock_delete_user, mock_update_groups
|
self, mock_delete_user, mock_logger, mock_update_groups
|
||||||
):
|
):
|
||||||
mock_update_groups.return_value = None
|
mock_update_groups.return_value = None
|
||||||
|
|
||||||
@@ -222,6 +234,72 @@ class TestTaskPerformUserAction(TestCase):
|
|||||||
tasks._task_perform_user_action(mock_task, self.user.pk, 'update_groups')
|
tasks._task_perform_user_action(mock_task, self.user.pk, 'update_groups')
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.DiscordUser.objects.server_name')
|
||||||
|
@patch(MODULE_PATH + ".logger")
|
||||||
|
class TestTaskUpdateServername(TestCase):
|
||||||
|
|
||||||
|
def test_normal(self, mock_logger, mock_server_name):
|
||||||
|
tasks.update_servername()
|
||||||
|
self.assertTrue(mock_server_name.called)
|
||||||
|
self.assertFalse(mock_logger.error.called)
|
||||||
|
_, kwargs = mock_server_name.call_args
|
||||||
|
self.assertFalse(kwargs["use_cache"])
|
||||||
|
|
||||||
|
def test_retries_on_api_backoff(self, mock_logger, mock_server_name):
|
||||||
|
mock_server_name.side_effect = DiscordApiBackoff(999)
|
||||||
|
|
||||||
|
with self.assertRaises(Retry):
|
||||||
|
tasks.update_servername()
|
||||||
|
|
||||||
|
self.assertFalse(mock_logger.error.called)
|
||||||
|
|
||||||
|
def test_retry_on_http_error(self, mock_logger, mock_server_name):
|
||||||
|
mock_exception = HTTPError(MagicMock(**{"response.status_code": 500}))
|
||||||
|
mock_server_name.side_effect = mock_exception
|
||||||
|
|
||||||
|
with self.assertRaises(Retry):
|
||||||
|
tasks.update_servername()
|
||||||
|
|
||||||
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
|
def test_retry_on_connection_error(self, mock_logger, mock_server_name):
|
||||||
|
mock_server_name.side_effect = ConnectionError
|
||||||
|
|
||||||
|
with self.assertRaises(Retry):
|
||||||
|
tasks.update_servername()
|
||||||
|
|
||||||
|
self.assertTrue(mock_logger.warning.called)
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.DISCORD_TASKS_MAX_RETRIES', 3)
|
||||||
|
def test_log_error_if_retries_exhausted(self, mock_logger, mock_server_name):
|
||||||
|
mock_task = MagicMock(**{'request.retries': 3})
|
||||||
|
mock_server_name.side_effect = ConnectionError
|
||||||
|
update_groups_inner = tasks.update_servername.__wrapped__.__func__
|
||||||
|
|
||||||
|
update_groups_inner(mock_task)
|
||||||
|
self.assertTrue(mock_logger.error.called)
|
||||||
|
|
||||||
|
|
||||||
|
@patch(MODULE_PATH + '.DiscordUser.objects.server_name')
|
||||||
|
class TestTaskPerformUsersAction(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
|
||||||
|
def test_raise_value_error_on_unknown_method(self, mock_server_name):
|
||||||
|
mock_task = MagicMock(**{'request.retries': 0})
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
tasks._task_perform_users_action(mock_task, 'invalid_method')
|
||||||
|
|
||||||
|
def test_catch_and_log_unexpected_exceptions(self, mock_server_name):
|
||||||
|
mock_server_name.side_effect = RuntimeError
|
||||||
|
mock_task = MagicMock(**{'request.retries': 0})
|
||||||
|
|
||||||
|
tasks._task_perform_users_action(mock_task, 'server_name')
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CELERY_ALWAYS_EAGER=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True)
|
||||||
class TestBulkTasks(TestCase):
|
class TestBulkTasks(TestCase):
|
||||||
|
|
||||||
@@ -299,15 +377,19 @@ class TestBulkTasks(TestCase):
|
|||||||
|
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
@patch(MODULE_PATH + '.update_username.si')
|
@patch(MODULE_PATH + '.update_username')
|
||||||
def test_can_update_all_usernames(self, mock_update_username):
|
@patch(MODULE_PATH + '.update_servername')
|
||||||
|
def test_can_update_all_usernames(
|
||||||
|
self, mock_update_servername, mock_update_username
|
||||||
|
):
|
||||||
du_1 = DiscordUser.objects.create(user=self.user_1, uid=123)
|
du_1 = DiscordUser.objects.create(user=self.user_1, uid=123)
|
||||||
du_2 = DiscordUser.objects.create(user=self.user_2, uid=456)
|
du_2 = DiscordUser.objects.create(user=self.user_2, uid=456)
|
||||||
du_3 = DiscordUser.objects.create(user=self.user_3, uid=789)
|
du_3 = DiscordUser.objects.create(user=self.user_3, uid=789)
|
||||||
|
|
||||||
tasks.update_all_usernames()
|
tasks.update_all_usernames()
|
||||||
self.assertEqual(mock_update_username.call_count, 3)
|
self.assertTrue(mock_update_servername.delay.called)
|
||||||
current_pks = [args[0][0] for args in mock_update_username.call_args_list]
|
self.assertEqual(mock_update_username.si.call_count, 3)
|
||||||
|
current_pks = [args[0][0] for args in mock_update_username.si.call_args_list]
|
||||||
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
expected_pks = [du_1.pk, du_2.pk, du_3.pk]
|
||||||
self.assertSetEqual(set(current_pks), set(expected_pks))
|
self.assertSetEqual(set(current_pks), set(expected_pks))
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import re
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
from . import providers
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
GROUP_CACHE_MAX_AGE = getattr(settings, 'DISCOURSE_GROUP_CACHE_MAX_AGE', 2 * 60 * 60) # default 2 hours
|
GROUP_CACHE_MAX_AGE = getattr(settings, 'DISCOURSE_GROUP_CACHE_MAX_AGE', 2 * 60 * 60) # default 2 hours
|
||||||
@@ -19,128 +19,8 @@ class DiscourseError(Exception):
|
|||||||
return "API execution failed.\nErrors: %s\nEndpoint: %s" % (self.errors, self.endpoint)
|
return "API execution failed.\nErrors: %s\nEndpoint: %s" % (self.errors, self.endpoint)
|
||||||
|
|
||||||
|
|
||||||
# not exhaustive, only the ones we need
|
|
||||||
ENDPOINTS = {
|
|
||||||
'groups': {
|
|
||||||
'list': {
|
|
||||||
'path': "/groups/search.json",
|
|
||||||
'method': 'get',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'create': {
|
|
||||||
'path': "/admin/groups",
|
|
||||||
'method': 'post',
|
|
||||||
'args': {
|
|
||||||
'required': ['name'],
|
|
||||||
'optional': ['visible'],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'add_user': {
|
|
||||||
'path': "/admin/groups/%s/members.json",
|
|
||||||
'method': 'put',
|
|
||||||
'args': {
|
|
||||||
'required': ['usernames'],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'remove_user': {
|
|
||||||
'path': "/admin/groups/%s/members.json",
|
|
||||||
'method': 'delete',
|
|
||||||
'args': {
|
|
||||||
'required': ['username'],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'delete': {
|
|
||||||
'path': "/admin/groups/%s.json",
|
|
||||||
'method': 'delete',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'users': {
|
|
||||||
'create': {
|
|
||||||
'path': "/users",
|
|
||||||
'method': 'post',
|
|
||||||
'args': {
|
|
||||||
'required': ['name', 'email', 'password', 'username'],
|
|
||||||
'optional': ['active'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'update': {
|
|
||||||
'path': "/users/%s.json",
|
|
||||||
'method': 'put',
|
|
||||||
'args': {
|
|
||||||
'required': ['params'],
|
|
||||||
'optional': [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'get': {
|
|
||||||
'path': "/users/%s.json",
|
|
||||||
'method': 'get',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'activate': {
|
|
||||||
'path': "/admin/users/%s/activate",
|
|
||||||
'method': 'put',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'set_email': {
|
|
||||||
'path': "/users/%s/preferences/email",
|
|
||||||
'method': 'put',
|
|
||||||
'args': {
|
|
||||||
'required': ['email'],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'suspend': {
|
|
||||||
'path': "/admin/users/%s/suspend",
|
|
||||||
'method': 'put',
|
|
||||||
'args': {
|
|
||||||
'required': ['duration', 'reason'],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'unsuspend': {
|
|
||||||
'path': "/admin/users/%s/unsuspend",
|
|
||||||
'method': 'put',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'logout': {
|
|
||||||
'path': "/admin/users/%s/log_out",
|
|
||||||
'method': 'post',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'external': {
|
|
||||||
'path': "/users/by-external/%s.json",
|
|
||||||
'method': 'get',
|
|
||||||
'args': {
|
|
||||||
'required': [],
|
|
||||||
'optional': [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DiscourseManager:
|
class DiscourseManager:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -148,55 +28,14 @@ class DiscourseManager:
|
|||||||
SUSPEND_DAYS = 99999
|
SUSPEND_DAYS = 99999
|
||||||
SUSPEND_REASON = "Disabled by auth."
|
SUSPEND_REASON = "Disabled by auth."
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def __exc(endpoint, *args, **kwargs):
|
|
||||||
params = {
|
|
||||||
'api_key': settings.DISCOURSE_API_KEY,
|
|
||||||
'api_username': settings.DISCOURSE_API_USERNAME,
|
|
||||||
}
|
|
||||||
silent = kwargs.pop('silent', False)
|
|
||||||
if args:
|
|
||||||
endpoint['parsed_url'] = endpoint['path'] % args
|
|
||||||
else:
|
|
||||||
endpoint['parsed_url'] = endpoint['path']
|
|
||||||
data = {}
|
|
||||||
for arg in endpoint['args']['required']:
|
|
||||||
data[arg] = kwargs[arg]
|
|
||||||
for arg in endpoint['args']['optional']:
|
|
||||||
if arg in kwargs:
|
|
||||||
data[arg] = kwargs[arg]
|
|
||||||
for arg in kwargs:
|
|
||||||
if arg not in endpoint['args']['required'] and arg not in endpoint['args']['optional'] and not silent:
|
|
||||||
logger.warn("Received unrecognized kwarg %s for endpoint %s" % (arg, endpoint))
|
|
||||||
r = getattr(requests, endpoint['method'])(settings.DISCOURSE_URL + endpoint['parsed_url'], headers=params,
|
|
||||||
json=data)
|
|
||||||
try:
|
|
||||||
if 'errors' in r.json() and not silent:
|
|
||||||
logger.error("Discourse execution failed.\nEndpoint: %s\nErrors: %s" % (endpoint, r.json()['errors']))
|
|
||||||
raise DiscourseError(endpoint, r.json()['errors'])
|
|
||||||
if 'success' in r.json():
|
|
||||||
if not r.json()['success'] and not silent:
|
|
||||||
raise DiscourseError(endpoint, None)
|
|
||||||
out = r.json()
|
|
||||||
except ValueError:
|
|
||||||
out = r.text
|
|
||||||
finally:
|
|
||||||
try:
|
|
||||||
r.raise_for_status()
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
raise DiscourseError(endpoint, e.response.status_code)
|
|
||||||
return out
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_groups():
|
def _get_groups():
|
||||||
endpoint = ENDPOINTS['groups']['list']
|
data = providers.discourse.client.groups()
|
||||||
data = DiscourseManager.__exc(endpoint)
|
|
||||||
return [g for g in data if not g['automatic']]
|
return [g for g in data if not g['automatic']]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_group(name):
|
def _create_group(name):
|
||||||
endpoint = ENDPOINTS['groups']['create']
|
return providers.discourse.client.create_group(name=name[:20], visible=True)['basic_group']
|
||||||
return DiscourseManager.__exc(endpoint, name=name[:20], visible=True)['basic_group']
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _generate_cache_group_name_key(name):
|
def _generate_cache_group_name_key(name):
|
||||||
@@ -234,13 +73,11 @@ class DiscourseManager:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __add_user_to_group(g_id, username):
|
def __add_user_to_group(g_id, username):
|
||||||
endpoint = ENDPOINTS['groups']['add_user']
|
providers.discourse.client.add_group_member(g_id, username)
|
||||||
DiscourseManager.__exc(endpoint, g_id, usernames=username)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __remove_user_from_group(g_id, username):
|
def __remove_user_from_group(g_id, uid):
|
||||||
endpoint = ENDPOINTS['groups']['remove_user']
|
providers.discourse.client.delete_group_member(g_id, uid)
|
||||||
DiscourseManager.__exc(endpoint, g_id, username=username)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __generate_group_dict(names):
|
def __generate_group_dict(names):
|
||||||
@@ -252,39 +89,35 @@ class DiscourseManager:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def __get_user_groups(username):
|
def __get_user_groups(username):
|
||||||
data = DiscourseManager.__get_user(username)
|
data = DiscourseManager.__get_user(username)
|
||||||
return [g['id'] for g in data['user']['groups'] if not g['automatic']]
|
return [g['id'] for g in data['groups'] if not g['automatic']]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __user_name_to_id(name, silent=False):
|
def __user_name_to_id(name, silent=False):
|
||||||
data = DiscourseManager.__get_user(name, silent=silent)
|
data = DiscourseManager.__get_user(name)
|
||||||
return data['user']['id']
|
return data['user']['id']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __get_user(username, silent=False):
|
def __get_user(username, silent=False):
|
||||||
endpoint = ENDPOINTS['users']['get']
|
return providers.discourse.client.user(username)
|
||||||
return DiscourseManager.__exc(endpoint, username, silent=silent)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __activate_user(username):
|
def __activate_user(username):
|
||||||
endpoint = ENDPOINTS['users']['activate']
|
|
||||||
u_id = DiscourseManager.__user_name_to_id(username)
|
u_id = DiscourseManager.__user_name_to_id(username)
|
||||||
DiscourseManager.__exc(endpoint, u_id)
|
providers.discourse.client.activate(u_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __update_user(username, **kwargs):
|
def __update_user(username, **kwargs):
|
||||||
endpoint = ENDPOINTS['users']['update']
|
|
||||||
u_id = DiscourseManager.__user_name_to_id(username)
|
u_id = DiscourseManager.__user_name_to_id(username)
|
||||||
DiscourseManager.__exc(endpoint, u_id, params=kwargs)
|
providers.discourse.client.update_user(endpoint, u_id, **kwargs)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __create_user(username, email, password):
|
def __create_user(username, email, password):
|
||||||
endpoint = ENDPOINTS['users']['create']
|
providers.discourse.client.create_user(username, username, email, password)
|
||||||
DiscourseManager.__exc(endpoint, name=username, username=username, email=email, password=password, active=True)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __check_if_user_exists(username):
|
def __check_if_user_exists(username):
|
||||||
try:
|
try:
|
||||||
DiscourseManager.__user_name_to_id(username, silent=True)
|
DiscourseManager.__user_name_to_id(username)
|
||||||
return True
|
return True
|
||||||
except DiscourseError:
|
except DiscourseError:
|
||||||
return False
|
return False
|
||||||
@@ -292,30 +125,26 @@ class DiscourseManager:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def __suspend_user(username):
|
def __suspend_user(username):
|
||||||
u_id = DiscourseManager.__user_name_to_id(username)
|
u_id = DiscourseManager.__user_name_to_id(username)
|
||||||
endpoint = ENDPOINTS['users']['suspend']
|
return providers.discourse.client.suspend(u_id, DiscourseManager.SUSPEND_DAYS,
|
||||||
return DiscourseManager.__exc(endpoint, u_id, duration=DiscourseManager.SUSPEND_DAYS,
|
DiscourseManager.SUSPEND_REASON)
|
||||||
reason=DiscourseManager.SUSPEND_REASON)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __unsuspend(username):
|
def __unsuspend(username):
|
||||||
u_id = DiscourseManager.__user_name_to_id(username)
|
u_id = DiscourseManager.__user_name_to_id(username)
|
||||||
endpoint = ENDPOINTS['users']['unsuspend']
|
return providers.discourse.client.unsuspend(u_id)
|
||||||
return DiscourseManager.__exc(endpoint, u_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __set_email(username, email):
|
def __set_email(username, email):
|
||||||
endpoint = ENDPOINTS['users']['set_email']
|
return providers.discourse.client.update_email(username, email)
|
||||||
return DiscourseManager.__exc(endpoint, username, email=email)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __logout(u_id):
|
def __logout(u_id):
|
||||||
endpoint = ENDPOINTS['users']['logout']
|
return providers.discourse.client.log_out(u_id)
|
||||||
return DiscourseManager.__exc(endpoint, u_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __get_user_by_external(u_id):
|
def __get_user_by_external(u_id):
|
||||||
endpoint = ENDPOINTS['users']['external']
|
data = providers.discourse.client.user_by_external_id(u_id)
|
||||||
return DiscourseManager.__exc(endpoint, u_id)
|
return data
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __user_id_by_external_id(u_id):
|
def __user_id_by_external_id(u_id):
|
||||||
@@ -351,7 +180,9 @@ class DiscourseManager:
|
|||||||
logger.debug("Updating discourse user %s groups to %s" % (user, groups))
|
logger.debug("Updating discourse user %s groups to %s" % (user, groups))
|
||||||
group_dict = DiscourseManager.__generate_group_dict(groups)
|
group_dict = DiscourseManager.__generate_group_dict(groups)
|
||||||
inv_group_dict = {v: k for k, v in group_dict.items()}
|
inv_group_dict = {v: k for k, v in group_dict.items()}
|
||||||
username = DiscourseManager.__get_user_by_external(user.pk)['user']['username']
|
discord_user = DiscourseManager.__get_user_by_external(user.pk)
|
||||||
|
username = discord_user['username']
|
||||||
|
uid = discord_user['id']
|
||||||
user_groups = DiscourseManager.__get_user_groups(username)
|
user_groups = DiscourseManager.__get_user_groups(username)
|
||||||
add_groups = [group_dict[x] for x in group_dict if not group_dict[x] in user_groups]
|
add_groups = [group_dict[x] for x in group_dict if not group_dict[x] in user_groups]
|
||||||
rem_groups = [x for x in user_groups if x not in inv_group_dict]
|
rem_groups = [x for x in user_groups if x not in inv_group_dict]
|
||||||
@@ -364,7 +195,7 @@ class DiscourseManager:
|
|||||||
logger.info(
|
logger.info(
|
||||||
"Updating discourse user %s groups: removing %s" % (username, rem_groups))
|
"Updating discourse user %s groups: removing %s" % (username, rem_groups))
|
||||||
for g in rem_groups:
|
for g in rem_groups:
|
||||||
DiscourseManager.__remove_user_from_group(g, username)
|
DiscourseManager.__remove_user_from_group(g, uid)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def disable_user(user):
|
def disable_user(user):
|
||||||
|
|||||||
@@ -16,3 +16,4 @@ class DiscourseUser(models.Model):
|
|||||||
permissions = (
|
permissions = (
|
||||||
("access_discourse", u"Can access the Discourse service"),
|
("access_discourse", u"Can access the Discourse service"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
19
allianceauth/services/modules/discourse/providers.py
Normal file
19
allianceauth/services/modules/discourse/providers.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from pydiscourse import DiscourseClient
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
class DiscourseAPIClient():
|
||||||
|
_client = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def client(self):
|
||||||
|
if not self._client:
|
||||||
|
self._client = DiscourseClient(
|
||||||
|
settings.DISCOURSE_URL,
|
||||||
|
api_username=settings.DISCOURSE_API_USERNAME,
|
||||||
|
api_key=settings.DISCOURSE_API_KEY)
|
||||||
|
return self._client
|
||||||
|
|
||||||
|
discourse = DiscourseAPIClient()
|
||||||
@@ -47,7 +47,8 @@ class DiscourseTasks:
|
|||||||
logger.debug("Updating discourse groups for user %s" % user)
|
logger.debug("Updating discourse groups for user %s" % user)
|
||||||
try:
|
try:
|
||||||
DiscourseManager.update_groups(user)
|
DiscourseManager.update_groups(user)
|
||||||
except:
|
except Exception as e:
|
||||||
|
logger.exception(e)
|
||||||
logger.warn("Discourse group sync failed for %s, retrying in 10 mins" % user)
|
logger.warn("Discourse group sync failed for %s, retrying in 10 mins" % user)
|
||||||
raise self.retry(countdown=60 * 10)
|
raise self.retry(countdown=60 * 10)
|
||||||
logger.debug("Updated user %s discourse groups." % user)
|
logger.debug("Updated user %s discourse groups." % user)
|
||||||
@@ -63,3 +64,4 @@ class DiscourseTasks:
|
|||||||
def get_username(user):
|
def get_username(user):
|
||||||
from .auth_hooks import DiscourseService
|
from .auth_hooks import DiscourseService
|
||||||
return NameFormatter(DiscourseService(), user).format_name()
|
return NameFormatter(DiscourseService(), user).format_name()
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ class ExampleService(ServicesHook):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
urls = self.Urls()
|
urls = self.Urls()
|
||||||
urls.auth_activate = 'auth_example_activate'
|
# urls.auth_activate = 'auth_example_activate'
|
||||||
urls.auth_deactivate = 'auth_example_deactivate'
|
# urls.auth_deactivate = 'auth_example_deactivate'
|
||||||
urls.auth_reset_password = 'auth_example_reset_password'
|
# urls.auth_reset_password = 'auth_example_reset_password'
|
||||||
urls.auth_set_password = 'auth_example_set_password'
|
# urls.auth_set_password = 'auth_example_set_password'
|
||||||
return render_to_string(self.service_ctrl_template, {
|
return render_to_string(self.service_ctrl_template, {
|
||||||
'service_name': self.title,
|
'service_name': self.title,
|
||||||
'urls': urls,
|
'urls': urls,
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.1.2 on 2020-10-11 10:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mumble', '0010_mumbleuser_certhash'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mumbleuser',
|
||||||
|
name='pwhash',
|
||||||
|
field=models.CharField(max_length=90),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -63,7 +63,7 @@ class MumbleManager(models.Manager):
|
|||||||
|
|
||||||
class MumbleUser(AbstractServiceModel):
|
class MumbleUser(AbstractServiceModel):
|
||||||
username = models.CharField(max_length=254, unique=True)
|
username = models.CharField(max_length=254, unique=True)
|
||||||
pwhash = models.CharField(max_length=80)
|
pwhash = models.CharField(max_length=90)
|
||||||
hashfn = models.CharField(max_length=20, default='sha1')
|
hashfn = models.CharField(max_length=20, default='sha1')
|
||||||
groups = models.TextField(blank=True, null=True)
|
groups = models.TextField(blank=True, null=True)
|
||||||
certhash = models.CharField(
|
certhash = models.CharField(
|
||||||
|
|||||||
@@ -211,4 +211,4 @@ class MumbleManagerTestCase(TestCase):
|
|||||||
pwhash = self.manager.gen_pwhash('test')
|
pwhash = self.manager.gen_pwhash('test')
|
||||||
|
|
||||||
self.assertEqual(pwhash[:15], '$bcrypt-sha256$')
|
self.assertEqual(pwhash[:15], '$bcrypt-sha256$')
|
||||||
self.assertEqual(len(pwhash), 75)
|
self.assertEqual(len(pwhash), 83)
|
||||||
|
|||||||
@@ -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 "Jabber Broadcast" %}{% endblock page_title %}
|
{% block page_title %}{% trans "Jabber Broadcast" %}{% endblock page_title %}
|
||||||
|
|||||||
@@ -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 "Verify Teamspeak" %}{% endblock page_title %}
|
{% block page_title %}{% trans "Verify Teamspeak" %}{% endblock page_title %}
|
||||||
|
|||||||
@@ -123,17 +123,12 @@ def m2m_changed_state_permissions(sender, instance, action, pk_set, *args, **kwa
|
|||||||
logger.debug("Permission change for state {} was not service permission, ignoring".format(instance))
|
logger.debug("Permission change for state {} was not service permission, ignoring".format(instance))
|
||||||
|
|
||||||
|
|
||||||
@receiver(state_changed, sender=UserProfile)
|
@receiver(state_changed)
|
||||||
def check_service_accounts_state_changed(sender, user, state, **kwargs):
|
def check_service_accounts_state_changed(sender, user, state, **kwargs):
|
||||||
logger.debug("Received state_changed from %s to state %s" % (user, state))
|
logger.debug("Received state_changed from %s to state %s" % (user, state))
|
||||||
service_perms = [svc.access_perm for svc in ServicesHook.get_services()]
|
for svc in ServicesHook.get_services():
|
||||||
state_perms = ["{}.{}".format(perm.natural_key()[1], perm.natural_key()[0]) for perm in state.permissions.all()]
|
svc.validate_user(user)
|
||||||
for perm in service_perms:
|
svc.update_groups(user)
|
||||||
if perm not in state_perms:
|
|
||||||
for svc in ServicesHook.get_services():
|
|
||||||
if svc.access_perm == perm:
|
|
||||||
logger.debug("User %s new state %s does not have service %s permission. Checking account." % (user, state, svc))
|
|
||||||
svc.validate_user(user)
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_delete, sender=User)
|
@receiver(pre_delete, sender=User)
|
||||||
@@ -159,24 +154,37 @@ def disable_services_on_inactive(sender, instance, *args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
@receiver(pre_save, sender=UserProfile)
|
@receiver(pre_save, sender=UserProfile)
|
||||||
def process_main_character_change(sender, instance, *args, **kwargs):
|
def process_main_character_change(sender, instance, *args, **kwargs):
|
||||||
|
if not instance.pk:
|
||||||
if not instance.pk: # ignore
|
# ignore new model being created
|
||||||
# new model being created
|
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
|
logger.debug(
|
||||||
|
"Received pre_save from %s for process_main_character_change", instance
|
||||||
|
)
|
||||||
old_instance = UserProfile.objects.get(pk=instance.pk)
|
old_instance = UserProfile.objects.get(pk=instance.pk)
|
||||||
if old_instance.main_character and not instance.main_character: # lost main char disable services
|
if old_instance.main_character and not instance.main_character:
|
||||||
logger.info("Disabling services due to loss of main character for user {0}".format(instance.user))
|
logger.info(
|
||||||
|
"Disabling services due to loss of main character for user %s",
|
||||||
|
instance.user
|
||||||
|
)
|
||||||
disable_user(instance.user)
|
disable_user(instance.user)
|
||||||
elif old_instance.main_character is not instance.main_character: # swapping/changing main character
|
elif old_instance.main_character != instance.main_character:
|
||||||
logger.info("Updating Names due to change of main character for user {0}".format(instance.user))
|
logger.info(
|
||||||
|
"Updating Names due to change of main character for user %s",
|
||||||
|
instance.user
|
||||||
|
)
|
||||||
for svc in ServicesHook.get_services():
|
for svc in ServicesHook.get_services():
|
||||||
try:
|
try:
|
||||||
svc.validate_user(instance.user)
|
svc.validate_user(instance.user)
|
||||||
svc.sync_nickname(instance.user)
|
svc.sync_nickname(instance.user)
|
||||||
except:
|
except:
|
||||||
logger.exception('Exception running sync_nickname for services module %s on user %s' % (svc, instance))
|
logger.exception(
|
||||||
|
"Exception running sync_nickname for services module %s "
|
||||||
|
"on user %s",
|
||||||
|
svc,
|
||||||
|
instance
|
||||||
|
)
|
||||||
|
|
||||||
except UserProfile.DoesNotExist:
|
except UserProfile.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
@@ -184,8 +192,12 @@ def process_main_character_change(sender, instance, *args, **kwargs):
|
|||||||
|
|
||||||
@receiver(pre_save, sender=EveCharacter)
|
@receiver(pre_save, sender=EveCharacter)
|
||||||
def process_main_character_update(sender, instance, *args, **kwargs):
|
def process_main_character_update(sender, instance, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
if instance.userprofile:
|
if instance.userprofile:
|
||||||
|
logger.debug(
|
||||||
|
"Received pre_save from %s for process_main_character_update",
|
||||||
|
instance
|
||||||
|
)
|
||||||
old_instance = EveCharacter.objects.get(pk=instance.pk)
|
old_instance = EveCharacter.objects.get(pk=instance.pk)
|
||||||
if not instance.character_name == old_instance.character_name or \
|
if not instance.character_name == old_instance.character_name or \
|
||||||
not instance.corporation_name == old_instance.corporation_name or \
|
not instance.corporation_name == old_instance.corporation_name or \
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user