Skip to content

Instantly share code, notes, and snippets.

@mcihad
Created August 27, 2025 09:14
Show Gist options
  • Save mcihad/0e19e8fbfdb4a0aad79d1357f2dcdc8c to your computer and use it in GitHub Desktop.
Save mcihad/0e19e8fbfdb4a0aad79d1357f2dcdc8c to your computer and use it in GitHub Desktop.
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
import re
VERB_MAP = {
'add': 'Ekleyebilir',
'change': 'Düzenleyebilir',
'delete': 'Silebilir',
'view': 'Görüntüleyebilir',
'assign': 'Atayabilir',
'approve': 'Onaylayabilir',
}
class Command(BaseCommand):
help = 'Veritabanındaki tüm permission isimlerini Türkçeleştirir (where possible)'
def handle(self, *args, **options):
perms = Permission.objects.select_related('content_type').all()
changed = []
skipped = []
for perm in perms:
original_name = perm.name
new_name = None
# try to get model verbose name
model_verbose = None
try:
model_cls = perm.content_type.model_class()
if model_cls is not None:
model_verbose = getattr(model_cls._meta, 'verbose_name', None)
if model_verbose:
# Ensure title case and strip
model_verbose = str(model_verbose).strip().title()
except Exception:
model_verbose = None
# 1) use codename pattern like add_modelname
parts = perm.codename.split('_', 1)
if len(parts) > 1 and parts[0] in VERB_MAP:
verb_tr = VERB_MAP[parts[0]]
if model_verbose:
new_name = f"{model_verbose} {verb_tr}"
else:
# fallback to content_type.model
model_name = perm.content_type.model.replace('_', ' ').title()
new_name = f"{model_name} {verb_tr}"
# 2) try to parse English name like 'Can add department'
if not new_name:
m = re.match(r'^Can (add|change|delete|view|assign|approve) (.+)$', original_name, flags=re.IGNORECASE)
if m:
eng = m.group(1).lower()
verb_tr = VERB_MAP.get(eng)
if model_verbose:
new_name = f"{model_verbose} {verb_tr}"
else:
model_text = m.group(2).strip().title()
new_name = f"{model_text} {verb_tr}"
# 3) attempt simple replacements in the name string
if not new_name:
new_name = original_name
replaced = False
# Replace English verbs if present
for eng, tr in VERB_MAP.items():
# Replace capitalized and lower-case occurrences
if re.search(rf'\b{eng}\b', new_name, flags=re.IGNORECASE):
new_name = re.sub(rf'\b{eng}\b', tr, new_name, flags=re.IGNORECASE)
replaced = True
if replaced and model_verbose:
# if the name still contains the model's english word, swap it with model_verbose
eng_model = perm.content_type.model.replace('_', ' ').title()
if eng_model in new_name:
new_name = new_name.replace(eng_model, model_verbose)
# Normalize whitespace
new_name = re.sub(r'\s+', ' ', new_name).strip()
# If nothing changed, skip
if new_name and new_name != original_name:
perm.name = new_name
perm.save()
changed.append((original_name, new_name, perm.id))
else:
skipped.append((original_name, perm.id))
# Output summary
self.stdout.write('\n=== Permission Translation Summary ===')
self.stdout.write(f'Total permissions scanned: {perms.count()}')
self.stdout.write(f'Total updated: {len(changed)}')
if changed:
self.stdout.write('\nUpdated permissions:')
for orig, new, pid in changed:
self.stdout.write(f' - ({pid}) "{orig}" -> "{new}"')
self.stdout.write(f'\nTotal skipped (no change): {len(skipped)}')
if skipped:
self.stdout.write('Skipped examples:')
for orig, pid in skipped[:10]:
self.stdout.write(f' - ({pid}) "{orig}"')
self.stdout.write('\nDone.')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment