1

I am looking to do language translations for my app. Accessing the translations from dictionaries in another py file makes the most sense to me.

I can technically access the dictionary values, but I cannot make the values change in the KV file when a button is pressed. Any guidance would be sincerely appreciated!

main.py

from kivy.app import App
from kivy.lang import Builder

kv_file = Builder.load_string("""
#:import pyfile pyfile
ScreenManager:
    id: manager
    Screen:
        GridLayout:
            cols:1
            rows:5
            Button:
                text: 'To English'
                on_release:
                    pyfile.rando().chosen_language = pyfile.rando().English
            Button:
                text: 'To Croatian'
                on_release:
                    pyfile.rando().chosen_language = pyfile.rando().Croatian
            Label:
                text:
                    pyfile.rando().chosen_language['MS First Button']
""")

class MyApp(App):

    def build(self):
        return kv_file

if __name__ == '__main__':
    MyApp().run()

pyfile.py

# -*- coding: utf-8 -*-
from kivy.properties import DictProperty

class rando(DictProperty):

    English = {'MS First Button': 'Take the Quiz'
    }

    Croatian = {'MS First Button': 'Učinite Kviz'
    }

    chosen_language = English
Petar Luketina
  • 449
  • 6
  • 18
  • Possible duplicate of [Importing variables from another file?](https://stackoverflow.com/questions/17255737/importing-variables-from-another-file) – Eb946207 Dec 18 '18 at 23:26
  • @EthanK , I changed the title. Sorry, I described the situation better in the description. I can access it fine, but I can't make it change the UI in Kivy – Petar Luketina Dec 18 '18 at 23:33
  • It should still work the same. Just import the class and get its objects. Do you have the right path? – Eb946207 Dec 18 '18 at 23:35
  • Yes, I can access it but that doesn't seem to update the label. It should, because it set as a property. If you run the code, you can see that the label grabs the value from `pyfile.py` – Petar Luketina Dec 18 '18 at 23:38
  • @EthanK Hold up, if I import the whole file, I don't need to import the class, correct? Because it seems to let me access it, or else the label would have nothing written in it. – Petar Luketina Dec 18 '18 at 23:42
  • Yes. If you do `import pyfile`, then you can do `pyfile.rando.English` to get the `English` dict. – Eb946207 Dec 18 '18 at 23:57
  • @PetarLuketina According to what I see you want to enable the property of internationalization to your application and so you can change the language in runtime and I see that you are doing it incorrectly. For those cases it is better to use poedit with gettext module. Is that your underlying problem? – eyllanesc Dec 19 '18 at 00:03
  • @eyllanesc , yes, I would like to press a button that changes the language of my buttons and labels. I've heard of po but not poedit. Do you have any resources? – Petar Luketina Dec 19 '18 at 00:08
  • @PetarLuketina po and poedit are part of the same, po is the format and poedit is an editor that allows creating .po files, on the other hand I recommend asking about your main objective instead of a possible solution that as we see does not work, that is Call [XY problem](http://xyproblem.info/). If your doing it could provide a solution but since your question is currently my answer would not be valid. – eyllanesc Dec 19 '18 at 00:11
  • @eyllanesc I understand. For the sake of understanding python and kivy more, why is my code not working, and how would I fix it? – Petar Luketina Dec 19 '18 at 00:15
  • @PetarLuketina inclement has the correct explanation of why your code does not work but unfortunately if the example is not correct so taking the explanation I have implemented the solution: https://gist.github.com/eyllanesc/50396b977821eb99cda97c5241fcd4ec – eyllanesc Dec 19 '18 at 00:31
  • @eyllanesc Thank you! I used your code and I made it into two .py files. I will post the answer and credit you as well. – Petar Luketina Dec 19 '18 at 00:56
  • @PetarLuketina I recommend that you mark the solution of `inclement` since there is the solution except that I do not test its code and therefore did not correct the problems that arise in runtime but the central idea is correct. – eyllanesc Dec 19 '18 at 00:58
  • @eyllanesc can you see if my solution is different from `inclement`? I used your code but split it into two files. – Petar Luketina Dec 19 '18 at 01:02

2 Answers2

1
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import DictProperty

kv_file = Builder.load_string("""
#:import pyfile pyfile
ScreenManager:
    id: manager
    Screen:
        GridLayout:
            cols:1
            rows:5
            Button:
                text: 'To English'
                on_release: app.translation_dict = app.English
            Button:
                text: 'To Croatian'
                on_release: app.translation_dict = app.Croatian

            Label:
                text:
                    app.translation_dict['MS First Button']
""")



class MyApp(App):

    English = {'MS First Button': 'Take the Quiz'}

    Croatian = {'MS First Button': 'Učinite Kviz'}

    translation_dict = DictProperty(English)

    def build(self):
        return kv_file

if __name__ == '__main__':
    MyApp().run()

Your use of a DictProperty just isn't right, properties only work when created at class level in an EventDispatcher. They are actually a special type of Python object called descriptors, you can look that up to see how they work.

The above code is quick adjustment to show a way to do things that would work, just as an example of a valid logic flow (not tested).

inclement
  • 29,124
  • 4
  • 48
  • 60
  • Your code does not work, using the same idea I have implemented the workable solution: https://gist.github.com/eyllanesc/50396b977821eb99cda97c5241fcd4ec, can I replace it in your code? – eyllanesc Dec 19 '18 at 00:28
  • @inclement thank you for pitching in! `eyllansc` helped steer me into the right direction as well. I posted the final version of my working code. Using dictionaries is the easiest way for me to change languages, but if you think that this is inefficient, please let me know how you would go about it. – Petar Luketina Dec 19 '18 at 01:11
0

Eyllanesc and Inclement helped to find a resolution. Thank you both!!

main.py

from kivy.app import App
from kivy.lang import Builder

kv_file = Builder.load_string("""
#:import pyfile pyfile
Manager:
    id: manager
    Screen:
        GridLayout:
            cols:1
            rows:3
            Button:
                text: 'To English'
                on_release:
                    manager.chosen_language = pyfile.Manager().English
            Button:
                text: 'To Croatian'
                on_release:
                    manager.chosen_language = manager.Croatian
            Button:
                text:
                    manager.chosen_language['MS First Button']
""")

class MyApp(App):

    def build(self):
        return kv_file

if __name__ == '__main__':
    MyApp().run()

pyfile.py

# -*- coding: utf-8 -*-
from kivy.properties import DictProperty
from kivy.uix.screenmanager import ScreenManager

class Manager(ScreenManager):

    English = {'MS First Button': 'Take the Quiz'
    }

    Croatian = {'MS First Button': 'Učinite Kviz'
    }
    chosen_language = DictProperty(Croatian)
Petar Luketina
  • 449
  • 6
  • 18
  • Your code does not work, it throws me the error: `kivy.factory.FactoryException: Unknown class ` And clearly the error is because Manager is not defined. Where have you created the Manager class? – eyllanesc Dec 19 '18 at 01:04