Package: sl10n
sl10nsl10n is a library that takes a unique approach
to dealing with localization by using statically typed translation keys.FeaturesType-safe:we use statically typed translation keys,
so you don't have to worry about making a typo or using a wrong key.Explicit:you get the exact result that you expect.Versatile: you can use it in any project.Self-sufficient, no other tools required.Written purely on Python.Easy to use.Small.Why?Imagine you have alangfolder
containing all our translation files and a parser
that reads these files and stores them in a mapping.{"my_key_1":"My text","my_key_2":"Wrong text"}importparser# your handwritten parserlocales=parser.parse('/lang')locale=locales.get('en')print(locale.get('my_key_1'))# My textYou may probably think "Sounds pretty simple" and you'd be right.
This approach is pretty common (e.g., Minecraft mods use it).But it's really error-prone.
You can easily make a typo or refer to a different key with similar name.print(locale.get('my_key_I'))# my_key_Iprint(locale.get('my_key_2'))# Wrong textThis becomes a real trouble once you
change the schema of your translation files and even IDEs won't help you.So?sl10n fixes this by introducinglocale containers.In short, alocale containeris a spec
of your translation files that contains all possible keys.
At parsing, all your localization gets collected
into locale containers, so you can access them freely.sl10n defines a base class for your locale container (SLocale)
and a parsing system (SL10n).fromsl10nimportSL10n,SLocaleclassMyLocale(SLocale):# your locale container, it MUST inherit from SLocalemy_key_1:strmy_key_2:strl10n=SL10n(MyLocale,'lang')# creating a reference for systeml10n.init()# execute parserThe key difference is that now you can
access your translated strings as class attributes.locale:MyLocale=l10n.locale('en')# returns default one if this language wasn't foundprint(locale.my_key_1)# My textThat way, your IDE can suggest what keys you can use
and also tell you if you made a typo.print(locale.my_key_I)# Unresolved attribute reference 'my_key_I for class 'MyLocale'You can still access your locale container dynamically
if you want (e.g. when the key is known only at runtime).key=f()# returned 'my_key_1'print(locale.get(key))# My textOther features?If your translation files don't follow the spec -SL10nwill notify you and also try to fix it:add all undefined keysmove all unexpected keys to the bottom of the fileYou can also create new translation files:fromsl10nimportSL10n,SLocaleclassMyLocale(SLocale):my_key_1:strmy_key_2:strl10n=SL10n(MyLocale,'lang')l10n.create_lang_file('de')# copy the contents of default language file ('en') to a new fileDefine what filenames should be ignored:l10n=SL10n(MyLocale,'lang',ignore_filenames=['config','tags'])Make a custom parsing implementation:fromsl10nimportSL10nfromsl10n.pimplimportParsingImplimportyamlclassYAMLImpl(ParsingImpl):file_ext='yml'def__init__(self,module=yaml,*args,**kwargs):self.module=moduleself.args=argsself.kwargs=kwargsdefload(self,file):returnself.module.load(file,self.loader)# yaml.load and yaml.dump are not safedefdump(self,data,file):self.module.dump(data,file,self.dumper,*self.args,**self.kwargs)...l10n=SL10n(MyLocale,'lang',parsing_impl=YAMLImpl())Apply some modifiers to your file (todo: make a docs explaining modifiers):{"my_key_1":"My text","my_key_2":"Wrong text","$redump":true// redumps the file anyway}{"my_key_1":"My text","my_key_2":"<not finished>","$exclude":true// excludes the file from parsing}