How to get a nice populated list of Languages in your Django app

(0 comments)

Since I wanted to make an inventory app (that i will likely post the source of - as FOSS of course - at some point when I am done) I wanted to have a model for languages with their ISO 639-1 code.

Now the model itself is of course easy, but where to get the data to popluate it.. I was certainly not going to do that manually. After a bit of searching and talking to people on IRC I dug a bit aorund the django I18N / L10N code and found something I could use: django.conf.locale.LANG_INFO While this is without a doubt used interanally for django, I thought that would be awesome to just use that as  base for my data.

The next point was how to get the data into my DB without too much effort, but reproduceable. The first thing that came to mind was to write my own migration and populate it from there. Not somethign I particularily liked since I have a tendency to wipe my migrations and start from scratch during development and I was sure i'd delete just that one-too-many.

The other - and in my opinion better- option I found was more flexible as to when it was run and also beautifully simple: just write my own Custom Management command to do the data import for me. Using the Django documentation on custom management commands as base I got this working very quickly. Enough rambling .. here's the code:

first the model (since it was in the source data i added name_local cuz it is probably useful sometimes):

class Language(models.Model):
    '''
    List of languages by iso code (2 letter only because country code
    is not needed.
    This should be popluated by getting data from django.conf.locale.LANG_INFO
    '''
    name = models.CharField(max_length=256,
                            null=False,
                            blank=False,
                            verbose_name=_('Language name')
                            )
    name_local = models.CharField(max_length=256,
                                  null=False,
                                  blank=True,
                                  default='',
                                  verbose_name=_('Language name (in that language)'))
    isocode = models.CharField(max_length=2,
                               null=False,
                               blank=False,
                               unique=True,
                               verbose_name=_('ISO 639-1 Language code'),
                               help_text=_('2 character language code without country')
                               )
    sorting = models.PositiveIntegerField(blank=False,
                                          null=False,
                                          default=0,
                                          verbose_name=_('sorting order'),
                                          help_text=_('increase to show at top of the list')
                                          )

    def __str__(self):
        return '%s (%s)' % (self.name, self.name_local)

    class Meta:
        verbose_name = _('language')
        verbose_name_plural = _('languages')
        ordering = ('-sorting', 'name', 'isocode', )

(of course with gettext support, but if you don't need that just remove the _(...) ;)

Edit 2018-07-15: for usabilty reasons I added a sorting field so that commonly used langauges can be shown at the top of the list.

then create the folder <project>/management/commands directory and in that a file importlanguages.py

from django.core.management.base import BaseCommand, CommandError
from dcollect.models import Language
from django.conf.locale import LANG_INFO


class Command(BaseCommand):
    help = 'Imports language codes and names from django.conf.locale.LANG_INFO'

    def add_arguments(self, parser):
        pass

    def handle(self, *args, **options):
        cnt = 0
        for lang in LANG_INFO:
            if len(lang) == 2:
                #we only care about the 2 letter iso codes
                #self.stdout.write(lang + ' ' + LANG_INFO[lang]['name'] + ' ' + LANG_INFO[lang]['name_local'])
                try:
                    l = Language(isocode=lang,
                                 name=LANG_INFO[lang]['name'],
                                 name_local=LANG_INFO[lang]['name_local'])
                    l.save()
                    cnt += 1
                except Exception as e:
                    self.stdout.write('Error adding language %s' % lang)
        self.stdout.write('Added %d languages to dcollect' % cnt)

That was way easier than expected .. I initially was going to just populate 2 or 3 languages manually and leave the rest for later but that was so simple, that I just got it out of the way.

All that needs to be done now to import languages is python manage.py importlanguages - and the real nice part: no new dependencies added ;)

Currently unrated

Comments

There are currently no comments

New Comment

required

required (not published)

optional

required