Python Forum

Full Version: TypeError: string indices must be integers, not 'str'
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,
I'm learning python and tkinter and trying to create a multilingual project.
Everything works fine except the variable <a> which must fetch a language code (en, es, fr) in my database.
This <a> variable must be passed to the <pack> variable (pack=a) to translate pack["_title"] and pack["_menu"] from a Dictionary
Here is my problem:
- When I write <pack = es> (for Spanish) everything works fine and root.title(pack["_title"]) = MiTitulo
- But when I write <pack = a>, I get this error:
line 53, in <module>
root.title(pack["_title"])
TypeError: string indices must be integers, not 'str'
However, when I print <print(a)>, the output indicates <es>
THANKS

from tkinter import *
import sqlite3

root = Tk()

#-------------------------------------------> Dictionary pack lang
en = {
    "_title": "MyTitle",
    "_menu": "MyMenu",
}
fr = {
    "_title": "MonTitre",
    "_menu": "MonMenu",
}
es = {
    "_title": "MiTitulo",
    "_menu": "MiMenĂº",
}

#-------------------------------------------> connection database
pack = []
conn = sqlite3.connect('dataBase.db')
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS langPack (lang TEXT)")
rows = cursor.fetchall()
conn.commit()

rows = cursor.execute("SELECT * FROM langPack").fetchall()

for i in rows:
    a = i[0]
    print(a) # = es
    if a == "fr": x = 0
    if a == "en": x = 1
    if a == "es": x = 2
    
pack = fr # default value x = fr, en, es from database
# pack = a # not working

OPTIONS = ["fr", "en", "es"]

variable = StringVar(root)
variable.set(OPTIONS[x])  # default value x = fr, en, es from for i in rows (line 32)

w = OptionMenu(root, variable, *OPTIONS)
w.pack()

def ok():
    lang = variable.get()
    # delete all = delete previous language
    query = "DELETE FROM langPack"
    cursor.execute(query)
    conn.commit()
    # insert new choice of language
    query = "INSERT INTO langPack (lang) VALUES (?)"
    cursor.execute(query, (lang,))
    conn.commit()
#-------------------------------------------> end data base

button = Button(root, text="OK", command=ok)
button.pack(ipadx=50, ipady=30)

root.title(pack["_title"])

menuButton = Button(root, text=pack["_menu"])
menuButton.place(x=0, y=0)
menuButton.pack(ipadx=50, ipady=30)

root.mainloop()
Ignoring the database for now, your program cannot work because there is nothing linking the dictionary fr and the string "fr". Contrary to your comment "# default value x = fr, en, es from for i in rows (line 32)" x does not equal fr, en or es. it equals 0, 1 or 2. That is fairly worthless information because there is also no way to get from 0, 1 or 2 to fr, en or es.

Instead of having separate dictionaries for each language, I would have a dictionary of languages.
languages = {
    "en": {
        "_title": "MyTitle",
        "_menu": "MyMenu",
    },
    "fr": {
        "_title": "MonTitre",
        "_menu": "MonMenu",
    },
    "es": {
        "_title": "MiTitulo",
        "_menu": "MiMenĂº",
    },
}
Now you can use "en" to get the translation dictionary for "en". I use this dictionary in the program below.
import tkinter as tk  # Do not use wildcard imports


languages = {
    "en": {
        "_title": "MyTitle",
        "_menu": "MyMenu",
    },
    "fr": {
        "_title": "MonTitre",
        "_menu": "MonMenu",
    },
    "es": {
        "_title": "MiTitulo",
        "_menu": "MiMenĂº",
    },
}


def language_changed(*_):
    global language_pack
    lang = language_selection.get()
    language_pack = languages[lang]
    root.title(language_pack["_title"])
    translations.set("\n".join([f"{a}: {b}" for a, b in language_pack.items()]))


language_options = list(languages)
language_pack = languages[language_options[0]]

root = tk.Tk()
language_selection = tk.StringVar(root, language_options[0])
language_selection.trace_add("write", language_changed)
tk.OptionMenu(root, language_selection, *language_options).pack(padx=100, pady=10)

translations = tk.StringVar(root, "")
tk.Label(root, textvariable=translations).pack(padx=100, pady=10)

language_changed()

root.mainloop()
I left the database stuff out because I don't have your database, and it is not related to your current issue. But if I did have a database that I could use to get my translation language choices, I would use it like this:
language_options = [row[0] for row in cursor.execute("SELECT * FROM langPack")]
language = StringVar(root, language_options[0])
w = OptionMenu(root, language, *language_options)
deanhystad,
I adjusted your code and everything works perfectly, with the drop-down menu and the database.
Thank you so much.
You make my day !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
Smile Cool Wink