usernames: корректная транслитерация украинских букв в логинах
pytils (русская либа) выбрасывала і/ї/є/ґ/апостроф целиком: Кіт→kt, Філіпʼєв→flpv, Ірина→rina. Добавлен премаппинг украинских букв в латиницу до slugify (translit_login), общий для найма, импорта и конвертации. Теперь: Кіт Ірина → i.kit, Філіпʼєв Дмитро → d.filipiev, Ґудзик → gudzik. - apps/hiring/services: translit_login + _username_base через него - import_employees_json: переиспользует _username_base - tests: украинская транслитерация в convert_usernames Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -57,10 +57,9 @@ DEPT_73_NAME_TO_CODE = {
|
||||
|
||||
|
||||
def transliterate_username(last_name, first_name, taken):
|
||||
from pytils.translit import slugify
|
||||
# Формат: <первая буква имени>.<фамилия> (Иван Иванов -> i.ivanov).
|
||||
ln, fn = slugify(last_name), slugify(first_name)
|
||||
base = f'{fn[:1]}.{ln}'.strip('.') or 'user'
|
||||
from apps.hiring.services import _username_base
|
||||
base = _username_base(last_name, first_name)
|
||||
username = base
|
||||
counter = 1
|
||||
while username in taken or Employee.objects.filter(username=username).exists():
|
||||
|
||||
@@ -70,6 +70,18 @@ class ConvertUsernamesTests(TestCase):
|
||||
self.assertEqual(a.username, 'keepme') # исключён по логину
|
||||
self.assertEqual(b.username, 'petrov.s') # исключён по email
|
||||
|
||||
def test_ukrainian_transliteration(self):
|
||||
cases = {
|
||||
'kit.old': ('Ірина', 'Кіт', 'i.kit'),
|
||||
'flp.old': ('Дмитро', 'Філіпʼєв', 'd.filipiev'),
|
||||
'gud.old': ('Ганна', 'Ґудзик', 'g.gudzik'),
|
||||
}
|
||||
objs = {u: emp(u, first, last) for u, (first, last, _) in cases.items()}
|
||||
self._run(apply=True)
|
||||
for u, (_first, _last, expected) in cases.items():
|
||||
objs[u].refresh_from_db()
|
||||
self.assertEqual(objs[u].username, expected)
|
||||
|
||||
def test_excluded_username_is_reserved(self):
|
||||
# исключённый занимает 'p.petrov' — переименовываемый получит суффикс
|
||||
kept = emp('p.petrov', 'Павел', 'Петров', is_superuser=True)
|
||||
|
||||
+17
-3
@@ -11,11 +11,25 @@ from apps.employees.models.base import Employee
|
||||
from apps.hiring.models import HiringRequest, InternAccount
|
||||
|
||||
|
||||
# Украинские буквы, которые pytils (русская либа) выбрасывает целиком —
|
||||
# премаппим в латиницу до slugify, иначе Кіт→kt, Філіпʼєв→flpv и т.п.
|
||||
_UA_TRANSLIT = {
|
||||
'і': 'i', 'І': 'i', 'ї': 'i', 'Ї': 'i', 'є': 'ie', 'Є': 'ie',
|
||||
'ґ': 'g', 'Ґ': 'g', 'ʼ': '', '’': '', '‘': '', "'": '', '`': '',
|
||||
}
|
||||
|
||||
|
||||
def translit_login(text: str) -> str:
|
||||
"""Транслит для логина: украинские + русские буквы, нижний регистр, [a-z0-9]."""
|
||||
pre = ''.join(_UA_TRANSLIT.get(c, c) for c in (text or ''))
|
||||
return slugify(pre)
|
||||
|
||||
|
||||
def _username_base(last_name, first_name):
|
||||
"""Формат логина: <первая буква имени>.<фамилия>, транслит, нижний регистр.
|
||||
Иван Иванов -> i.ivanov."""
|
||||
ln = slugify(last_name)
|
||||
fn = slugify(first_name)
|
||||
Иван Иванов -> i.ivanov; Кіт Ірина -> i.kit."""
|
||||
ln = translit_login(last_name)
|
||||
fn = translit_login(first_name)
|
||||
initial = fn[:1]
|
||||
return f'{initial}.{ln}'.strip('.') or 'user'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user