Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[PyQt5] Translate QCombobox



  • Hi

    I would like to translate an app.
    Right now, I am using QTranslator and QTLinguist and most of the translation is ok.

    The only part I can not translate is few QCombobox in this application.

    These combobox get the list of item to display from a sqlite database (text stored in English) and I would like to be able to display these items in local language.

    I do not know how to handle this situation, if you have an idea ?



  • Actually, I finally chose a simplier solution.
    The main reason is that :

    • I do not want to modify the database structure
    • I want to make it easy to translate theses combobox

    So my solution is to use a dictionnary,

    • this dictionnary will be used to initialise the database (in english
    • using keys, I can choose which langage to display
    • this dictionnary is stored in a json file (easy to edit by translator)

  • Lifetime Qt Champion

    Hi,

    The simplest would be to provide that part of the translation through the database itself so it allows you to more easily provide updates for that data.


  • Banned

    This is typically done by translating the English into the various languages and storing those translations within the database in a sort of semi-generic fashion...

    That is to say you have an Id associated with the GUI text and then you XRef number that maps that Id to the specific language database Id for that text then the selected language id is used to finish up that referencing

    So a Language Table would contain

    LangId int  Pkey
    TextId int Pkey
    TextVrbg text
    

    Then you just "SELECT TextId, TextVrbg FROM tblDescrptions WHERE LangId =" + str(ChosnLang)

    Note the TextId from Language to the next would be the same for the same aspect for instances if Language1 had Id = 10 for "Open" and Language2's translation of that would be "Enter" the Id = 10 the difference would the LangId in this case thus allowing for unique records


  • Lifetime Qt Champion

    @Denni-0 while I don't disagree with the logic of the implementation, it might be a bit overkill. Having one column per translation could be enough and would allow a direct use in the combo box by just changing the column used.


  • Banned

    @SGaist Well it really depends on the complexity and/or the amount of text. Also the problem with doing it columnar based is that it is not generically expandable. If done as I outlined you can create a generic function that implements the code-side in such a way as to implement additions later on fairly seamlessly by only adding a record to the database and the receiver on the code side --- your suggested method requires a lot more changes to the database and the code base


  • Lifetime Qt Champion

    @Denni-0 as I wrote before, I don't disagree with the logic you are proposing. I just encourage to analyse the needs before creating a relational scheme that may or may not be overkill depending on the amount of data, the translation method used and the scope of the data.

    Out of curiosity, in what way do your consider a call to setModelColumn more complicated than your proposal ?


  • Banned

    If you mean setModelColumn is a reference to a column in a row within the a table within a database its not more complicated -- the complications come into play when you need to add a new column that did not exit before or remove one that currently exists

    My layout you simply either add a new row or remove a row from the database -- and add or remove the item from code that is/was being referenced nothing complicated at all -- yours not only do you have to add/remove that item but you have to add/remove that column from the table -- which is a lot more complex since that may mean you have to change some queries, etc.... Aka much more dangerous as a program grows... sure you can cut corners early on but in my experience these simple programs tend to grow and if you plan them appropriately from the get go you never have to re-engineer them later

    Lastly as I have sort of stated -- when I am planning a project big or small -- I am always looking far down the road so that I implement the best solution that answers the current needs with the least complexity while also leaving room for easy growth should that be needed -- which means creating a database for the data not for its implementation -- is that overkill -- I do not think so -- I look at it as solid coding -- coding which has made projects not take any more time to develop but save a truck load of effort later when the scope of what the users needed changed

    Still I only promote the things I found to be the best solution from get go versus what I see as half-solutions especially since the base amount of effort for the former and the latter are about the same



  • If the OP is prepared to define a SQL VIEW in the backend, which presents the data as columns for the convenience of QComboBox.setModelColumn(), this allows (to some extent) independence from whether the underlying table is stored with columns or rows for the languages, so he can either way on the implementation :)


  • Lifetime Qt Champion

    @Denni-0 said in [PyQt5] Translate QCombobox:

    If you mean setModelColumn is a reference to a column in a row within the a table within a database its not more complicated -- the complications come into play when you need to add a new column that did not exit before or remove one that currently exists

    "A column in a row within a table with a database" does not make much sens. SQL wise, using a QSqlTableModel, you just say which column of said model (and thus table) you want to use and the combobox will show you that.

    I am wondering if we are on the same line with regards to my suggestion. The table I was talking about would be (if using SQLite):

    create table items(id integer primary key, english varchar, german varchar, french varchar);
    

    One column per language supported.

    One thing for sure is that if you want to add or remove a supported language it will require a migration of the database. No doubt about that. However adding and removing items will only concern one row.



  • @SGaist said in [PyQt5] Translate QCombobox:

    One column per language supported.

    What I guess @Denni-0 is trying to show with your approach is that when you need to add a new language to the DB you need to alter the table structure just to add a new column.

    if you want to add or remove a supported language it will require a migration of the database.

    Not using @Denni-0 approach, you just add more rows for the new language or delete all rows for an existing language. No changes to table structure (no need to use DDL commands)


  • Lifetime Qt Champion

    @Pablo-J-Rogina I know exactly what @Denni-0 is explaining. You'll need one table for the language identification, one for the words and one for mapping the translations together because you'll want to have one as reference for further processing along and people will also be expecting that you have the items in the same order whatever the language. Therefore you structure should allow to grab all data in the same manner without having to worry which language you are using. You can always add sorting at the end if you really want to but that should rather be an option for the user.

    In the same answer you are quoting, I already explained (and insisted on) the need of a migration (structural change / data change) of the database if a language is added or removed.

    Again: I am not saying that @Denni-0 method is wrong or bad nor that my proposition is superior.

    It's just two solutions with pros and cons to take into account.


  • Banned

    Ah I think I see where the issue of what your stating actually resides -- you are not using MVC methodology which is a major issue unto itself -- learn how MVC should be implemented and quit encoding numerous issues that get created when you tie a database backend directly to the GUI frontend via the methodology you seem to be using --- yes it is available but it ought never be used in any code base these days as the Cons of doing so far out weigh any of the minor Pros it has


  • Lifetime Qt Champion

    I am not using MVC ?

    QComboBox -> View
    QSqlTableModel -> Model
    Database -> source of data for the model.

    There's no controller layer here because Qt uses Model/View rather than Model/View/Controller.

    You can use QSqlQueryModel for more involved queries like the one needed by your design. So you can combine QSqlQueryModel and QComboBox and there you have your MV pattern.

    Neither QSqlQueryModel nor QSqlTableModel cares about what database backend you are using.

    In any case, whatever technique you use, you have to configure database access before you can query it which is valid for any other generic framework you use to access a database (SQLAlchemy, Django's ORM, QtSql module, etc).

    Are you suggesting to query the database and generate the list of combobox entries based on the values returned by that query ? In what way does it untie you from the database ?

    In any case, please explain how you would populate that combo box with data coming from an SQLite database.


  • Banned

    No because in Qt the Model and View actually are not separate and also actually represent View/Controller joined into one entity -- so it being called a Model is wrong -- further this means that when you tie the database to that you have a single entity that represents View/Controller/Model -- a single entity not 3 separate entities

    In an actual MVC all three entities are autonomous as such the View knows absolutely nothing about the Database nor in fact where that data is coming from and the Database does not know nor does it care what or how the data it returns is being used -- both of these statements become false when you use the methodology you are promoting. Further in M<>C<>V everything passes through the Controller which handles all the translations from Model (Data Source) to View (GUI Displayer). And finally with this I can change either my View or my Model without effecting the other at all -- which again becomes a false statement using the methodology you are promoting thus again making your methodology not MVC

    Now does this mean that this tight binding between GUI and Database does not exit -- no as you have pointed out -- it is quite alive and kicking and used all over the place -- and I would counter with fairly problematic results -- as I have had to go in and clean that crap up from time to time -- as the issues got to be to big ... so on some scales this inferior approach can be utilized but since it takes as much effort to implement the inferior method as opposed to the superior one -- why not just use the superior one -- well often it boils down to one of two reasons -- lack of education -- or just pure laziness on the part of the coder and by that I mean lazy mindedness as the actually coding effort is basically the same they just perceive it as being easier

    Now how do I untie the database from the GUI by using straight MVC as it as it was meant to be used ---- wherein the View (GUI) is an autonomous entity (often a class or series of classes that are used to only render the data for viewing and interact with the user) that makes data requests to the Controller and gets back a result or a result sets (list or dictionary) from the Controller depending on the request made. Most importantly the actual source of that data is totally irrelevant and could be a file on the system, it could be a website, it could be a serial device, or it could be a database -- OR -- it could a combination of any or all of these but the GUI does not know nor does it care because its coding only deals with the data or data sets it gets back.

    On the flip side the database class is also a completely autonomous entity whose only job is to receive basic requests from the Controller and turn that request into a response. It handles everything and only those things that are associated with the type of database that is is aimed at. Allowing for quick and easy interchangeability by having an SQLite3 Database class, MySQL Database class, etc... having the same exterior calls (API interface) and that return the same sort of data responses to the Controller. Further once you have coded one these all you might have to tweak from one program to the next is your API calls the rest should pretty much stay the same as can be seen within my SQLite3 Database template I made for my students

    So I have my GUI <which talks to> Controller <which talks to> Database

    GUI Requests the Data for a ComboBox --> Controller takes this and sends it to the Data Source responsible for that (in this case the database where it was stored but it could have been a text file or a json file) --> Data Source gathers this particular data into a list and sends it back to the Controller which in turns sends it on to the GUI

    Now this might seem unnecessary but what happens when your GUI and Database are in two different processes due that being a necessity -- how would you handle that using your methodology (you can't) -- on the other hand my methodology basically handles the communication between these 3 entities the same way with all that needs changing is how to handle the communication mechanism -- further my actual GUI and Database Classes are completely unaffected by this since they were designed to be autonomous to begin with.

    I hope that helps you understand (1) What MVC really is and (2) The danger of using that inferior methodology you promote


  • Lifetime Qt Champion

    @Denni-0 said in [PyQt5] Translate QCombobox:

    No because in Qt the Model and View actually are not separate and also actually represent View/Controller joined into one entity -- so it being called a Model is wrong -- further this means that when you tie the database to that you have a single entity that represents View/Controller/Model -- a single entity not 3 separate entities

    That statement is pretty wrong. Qt's View classes are just GUI elements that shows one way or anther the content provided by a model. You don't need a view to use Qt's models. However I do agree that these models can contain elements that can modify the rendering of the view. But still they are not one entity as you write. A QTableView is a widget to show the content of a table like model (base on QAbstractTableModel, QSqlTableModel, etc), a QComboBox is a view on top of a model that has at least one column (again QAbstractTableModel, QAbstractListModel, QSqlTableModel, etc). Whatever feeds the model is of no concern to either QTableView, QComboBox or any of the other view you can put of on top of these models. Take the QFileSystemModel, it's a threaded model that loads filesystem content "on demand".

    Anyway, I am not promoting anything, I am discussing possibilities.

    If anything I am using the tools Qt proposes. Are they the only way to work ? Not at all. Are they always the best solution, again, not at all.

    I usually take the time to ponder what tool is the best for the situation at hand. Taking a sledgehammer for every type of nails is not the correct methodology.


  • Banned

    Actually the statement is Spot On -- and explained pretty much that way within their own documentation -- further Qt View does not require that you use a Qt Model (if I remember correctly) those are just nice tools and as such you do not need Qt Models to render a Qt View -- aka it works both ways

    So basically you are splitting hairs -- so okay yes they are not exactly a single entity -- BUT when used together they are not distinct autonomous entities either due to the fact they are tightly bound to one another making them pretty much a single non-separable entity if you plan to use them as prescribed

    Further yes the Qt Model (aka Controller) entity can be designed to be autonomous from the Data Source but your methodology was not doing that -- and when I say promoting it I am saying it is the idea you are putting forth as a possibility as no one else is putting that idea forth -- again you are splitting syntactical hairs when you say you are not promoting it

    Next those particular tools are not only not the best but perhaps one of the worst ways to implement said connectivity as I outlined -- yes but rarely (to almost never) is using an axe as you suggest a tool that one should use to pound a nail with using your analogy

    Look in a nutshell -- what I try to put forth are the concepts that are best to use in most if not all situations -- I rarely toy around with things (regardless of who provides them) with tools that utilize inferior methodologies such as those that do not implement a true MVC structure



  • Actually, I finally chose a simplier solution.
    The main reason is that :

    • I do not want to modify the database structure
    • I want to make it easy to translate theses combobox

    So my solution is to use a dictionnary,

    • this dictionnary will be used to initialise the database (in english
    • using keys, I can choose which langage to display
    • this dictionnary is stored in a json file (easy to edit by translator)

  • Banned

    @anto1ne okay and what you just did -- though you may not understand it this way -- is change your database but you did it by augmenting it externally and adding another layer of complexity to your program -- note a Json file is just simply a very simplistic database.

    Still if this works for what it is you want to do congratz on coming up with a solution that you feel comfortable with.


Log in to reply