otmezger
otmezger

Reputation: 10784

multi language support in python script

I have a large python (2.7) script that reads data from a database and generate pictures in pdf format. My pictures have strings for labels, etc...

Now I want to add a multi language support for the script, so I can generate the same pictures in different languages by passing a variable to my script.

I was thinking in having a class with all the strings and their translations in a dictionary. For example:

Strings['string1'] = {'de':'string in german', 'en': 'string in english'}

I could acces the strings with

my_needed_string = 'string1'
selected_language = 'en'
Strings[my_needed_string][selected_language]

is there a better, more professional way to do this? with "better" I mean more flexible and easier to maintain? I have at least 80 different strings in 2 or more languages.

Thanks

Upvotes: 8

Views: 19621

Answers (4)

LightWing
LightWing

Reputation: 98

If you only have a few languages, and don't want to use some i18n stuff, try one of these:

example (I'm just using a dict in a py file, let me know if you want specifically json):

also, this is written in python 3, not 2.

in en.py

en = {
    "eng": "english",
    "heb": "hebrew",
    "menu": {
        "menu1": "one",
        "menu2": "two"
    }
}

in he.py

he = {
    "eng": "אנגלית",
    "heb": "עברית",
    "menu": {
        "menu1": "אחד",
        "menu2": "שתיים"
    }
}

option 1 using SimpleNamespace:

from types import SimpleNamespace

#import language dicts from which ever folder and file they are, for me its the same folder and different files...
from .he import he
from .en import en

class NestedNamespace(SimpleNamespace):
    def __init__(self, dictionary, **kwargs):
        super().__init__(**kwargs)
        for key, value in dictionary.items():
            if isinstance(value, dict):
                self.__setattr__(key, NestedNamespace(value))
            else:
                self.__setattr__(key, value)

text = {}
text.update({"he": NestedNamespace(he)})
text.update({"en": NestedNamespace(en)})
print(text['he'].menu.menu1) #works

option 2 using namedtuple (i think this one is slower, by what i read about the way namedtuples are made, but im no pro, so choose whatever you like):

from collections import namedtuple

def customDictDecoder(dict1):
    for key, value in dict1.items():
        if type(value) is dict:
            dict1[key] = customDictDecoder(value)
    return namedtuple('X', dict1.keys())(*dict1.values())

text = {}
text.update({"he": customDictDecoder(he)})
text.update({"en": customDictDecoder(en)})
print(text['he'].menu.menu2) #works

if you want print(text.he.menu.menu1) to work, it is possible, but i dont see the use for it, if you want it, let me know

Upvotes: 5

Patrik Radics
Patrik Radics

Reputation: 63

A more 'pythonic way' could be if you just make a different .py and make a new class there with if statements for each language:

class Locale:
def __init__(self, loc):
    if loc == "en":
        self.string = "something in English"
    elif loc == "fr":
        self.string = "something in French"

Upvotes: -1

jolo Kp
jolo Kp

Reputation: 21

I had this problem a while ago and just solved it by creating two arrays with the words of the two languages I needed.

# array with english words
engList = ["dog", "cat"]
# array with german words
gerList = ["Hund", "Katze"]

Then I just set another array to the needed language array and use the words from this array.

# referenced array set to the english array
langList = engList

print(langList[0],"+",langList[1])

# change to the german array when needed
langList = gerList

print(langList[0],"+",langList[1])

Of course it's no way near to be perfect, but it worked for me. Hope I could help!

Upvotes: 0

Guy Gavriely
Guy Gavriely

Reputation: 11396

see python gettext module for i18n support

Upvotes: 11

Related Questions