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):
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,
name_local = models.CharField(max_length=256,
verbose_name=_('Language name (in that language)'))
isocode = models.CharField(max_length=2,
verbose_name=_('ISO 639-1 Language code'),
help_text=_('2 character language code without country')
sorting = models.PositiveIntegerField(blank=False,
help_text=_('increase to show at top of the list')
return '%s (%s)' % (self.name, self.name_local)
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
help = 'Imports language codes and names from django.conf.locale.LANG_INFO'
def add_arguments(self, parser):
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'])
l = Language(isocode=lang,
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 ;)