How to properly embed Qt 5.15 localizations in an iOS application - c++

Qt 5.15 introduces (at least I believe it is new to 5.15) .ts files, to allow for properly handling multi-locale text in an application. I'm updating an iOS Qt app from 5.X, where X knows nothing about .ts files. On startup, I'm getting a warning that indicates that there is an app-specific translation set (which is true), but that there is no translation for Qt's own text (things like warning text and dialog prompts). The documentation says, that these translations are in the Qt5 source directory (currently usually /tqtc-qt5) in the qtttranslations folder. Thus sayeth this doc https://doc.qt.io/qt-5/ios-platform-notes.html#application-assets. Examples show only app-unique text translations, not Qt's "built-in" text. So real quick, I'm going list my assumptions, so that they can be corrected or confirmed.
Qt has always had embedded text of its own, but 5.15 introduces a way to ensure that your multi-locale ready app has all the correctly translated "built-in" text available.
Only the app-writer knows what modules they are using, so it is the app-writer's responsibility to specify which set of translations are added to the app's resources for handling different locales. (per this document - https://doc.qt.io/qt-5/qmake-variable-reference.html#translations)
According to the above two docs, for example, if I use basic Qt functionality and QML, AND I have a single app with tier-one language support for, say, English, German, and French, it appears that my app's .pro file should include something like
TRANSLATIONS += <path_to_qt5>/qttranslations/qtbase_en.ts
TRANSLATIONS += <path_to_qt5>/qttranslations/qtbase_de.ts
TRANSLATIONS += <path_to_qt5>/qttranslations/qtbase_fr.ts
TRANSLATIONS += <path_to_qt5>/qttranslations/qtdeclarative_en.ts
TRANSLATIONS += <path_to_qt5>/qttranslations/qtdeclarative_de.ts
TRANSLATIONS += <path_to_qt5>/qttranslations/qtdeclarative_fr.ts
CONFIG += lrelease embed_translations
I've traced though the Qt source in the debugger to the point where it is complaining about the missing translations. It is looking for qt*_*.qm, where the first wildcard is your module ("base", "declarative", etc) and the second is your two-letter language code. So, should I be explicitly adding .qm files as resources in my iOS bundle, or is TRANSLATIONS += foo_ln.ts implicitly doing this embedding in response to CONFIG += lrelease embed_translations. One things is certain: right now, my naive porting of an older .pro file does nothing with respect the TRANSLATIONS property AND Qt is cranky about the missing .qm files in my bundle. It's a warning, not a critical fail, so I assume in a pinch, it would put up US english text, which seems to be the baseline for translations and is embedded in the source (not the bundle) by default. Do my example additions to the .pro file in point 3 above seem sufficient, or is there more to do? Or is there less to do? Is there a .pro directive that I've missed in the docs that says "do the right thing with international translations of Qt-inherent strings"? There is in a addition to the listed .ts files a "qt_*.ts" file set. Is this just everything whether I need it or not, for lazy people who don't care about lugging around a few extra strings? Finally, there is also EXTRA_TRANSLATIONS which is like TRANSLATIONS, only it does not go through the lupdate during the build. Now I'm pretty unclear on the function of lupdate relative to lrelease, but is it the case that one is for "stock" Qt strings, and the other for App-specific translations (because they may be "updated" due to changes during development)? The semantics just don't make sense to me right now, nor do my responsibilities to handle these matters in the "right" way.

I'd like to answer my own question because it turns out many of the above assumptions were just wrong, and it took deeper dives into the source code and the debugger to get my head straight, but now I have Wisdom. The documents I was reading was about how to include raw translation files "(.ts files)" into an app being built with qmake. As is typical with Qt, building with qmake or Qt Creator solves most of your problems automatically, with your part being to provide only the small amount of specification needed to execute your app. The app I'm working on however is monstrously huge, old, and overly-complicated, so I spend a lot of time hunting down the most obscure Qt and CMake features to cobble this Frankenstein's monster of an app together. The problem I was trying to solve is simply providing to Qt its own text localization files for a multi-locale app. The app-specific ones were fine, but Qt was wagging its finger at me and complaining that it couldn't find its own. So the .ts files it turns out are not a thing for this kind of task - they are simply part of the pipeline of getting data from a translation house in a consumable form. During Qt's own configure and build (yes we build Qt from source), it handles the compiling of raw .ts files into .qm files, suitable for use by the framework's translator objects. Those are all just sitting in qtbase/translations ready to be integrated into the app installation. The problem was that we (the group who developed this app long ago and which I am now reviving) didn't handle the iOS case. This is a special case that requires some choices. You can put translation files in the app's bundle at a specific path, you can home-brew some exotic URL resolution whereby you feed the translator the contents of the .qm files on demand, or you can compile them all into a .qrc file and position them in your resource tree. That last is what we did with the app-specific translations, so I mimicked it for Qt's, filtering the total set of .qm files for the modules we use and for the locales in our tier-one localization target languages. This involved a complicated python script, and a few extra lines of Cmake, including one very elusive one (QINIT_RESOURCES) that gated everything until I realized it was needed for this platform. I'm only wrapping this up, so if anyone else is confused enough to find this question, that there are some general comments to set things straight.

Related

QT How to find untranslated strings

I am testing a QT application I am internationalizing. I think I have found all the strings that need processing through tr() or ::Translate(). I think I have handled all occurrences.
I have gotten back the first rounds of translations (done through Qt linguist tool).
Through QA testing I want to make sure all strings are translated and if possible I would like to easily identify any that are not translated and why.
What tools or methods are available for this?
I have discovered
lrelease -markuntranslated <prefix>
This takes any strings in the .ts file that are untranslated and prepends prefix
If the label "do it now" is in the .ts file and it is not translated in Qt linguist, then if you run lrelease with
-markuntranslated NT-
then you will see the label presented when you run the application as 'NT-do it now'.
This makes it obvious for whomever is testing that the problem is a string that has been processed via ::Translate() or tr(), but which has not been translated in QT linguist.
And any wholly original strings in the UI of the running application must thus be fully untouched by any of the QT translation machinery.
see lrelease -help for more info.

Good way to maintain Qt labels and text on UI

What is the best way/common practice for maintaining all string resources found on a UI in Qt, especially the textual input/text in combo boxes etc. (since these are the once that are frequently used in the code itself)?
I know that Android has this string resources thing such that resources only have to be modified at one position.
Does Qt have something like that too or do I have to initialize string resources in code instead of in the UI's XML itself...
AFAIK, there is no built-in mechanism for string resources in Qt. If you want to maintain strings at build time you can define them in one .h/.cpp file as global variables and reuse them in your code.
Otherwise you can use Qt's translator files (binary) and load them along with your application. If you need to change a string, you simply will need to edit the translation file (xml) and "recompile" it with lrelease utility without building the application again.
There is a mechanism to dynamically translate texts in application, but it works a bit different than Android string resources, but achieves the same goals.
Qt uses i18n system modelled after standard, well known unix gettext. It works in a very similar way to iOS NSLocalizedString, if that rings a bell.
http://doc.qt.io/qt-5/qobject.html#tr
This is worth reading too:
http://en.wikipedia.org/wiki/Gettext
http://doc.qt.io/qt-5/internationalization.html
Android approach is a bit unique and you should not expect it to be a "standard everywhere". It works, it's ok, but it's not a standard way of doing things on desktop.

VC++ 10 MFC: What is the correct way to do localization

I am a .NET guy who is having to do some work on an MFC app. The app is a VS2008 MFC executable which I have converted to VS2010. The original developers did localisation by specifying the name of a .txt file with key value pairs in it on the applications command line. Installed shortcuts to the executable specify a different .txt file depending on which country the app is being installed in. This of course does not work if you just run the .exe directly. This seems like a weird way to do things to me.
I want to do this the propper MFC way, but I am having difficulty finding definitive answers on Google. My understanding is that the String Table in the .rc file should be used for this localisation? Is this the current best practice for MFC?
With respect to the String Table I have read that the practice is to create multiple string tables each for a different language. How do MFC applications choose which language to use? Is it based on the machines current language settings or can I control this (it may be that we want the language to be specified by the Wix .msi installer we are also building)?
I have also read that embedding all resource inside an MFC application has fallen out of favor and that now you should compile seperate resource .dlls? Is this is true ill investigate how to do it...
Finally, do I have to do something special to get MFC to support Unicode or is MFC Unicode by default?
Thanks
The idea is that all localizable items should be stored in resources. Standard UI objects such as menus and dialogs are automatically stored in there (resources) for you but items such as string literals (eg: error messages, messagebox prompts,...) should be pulled from source code to the string table. This short codeproject article of mine demonstrates how to easily pull strings from the string table in your code.
Note: You should have only one string table in your resource script (.rc).
From there on, you can translate your resources and create resource DLLs (aka satellite DLLs). The idea is that you keep a different copy of the .rc file(s) for each language. Each translation is compiled into a codeless DLL that acts as a container for the resources.
This other codeproject article of mine lets you easily load resource DLLs according to system settings or user preferences: The code looks among your resource DLLs which available language best matches user settings (based on user's UI language and regional settings). The code also lets you easily build a menu with all available languages. That way, your user can override the default choice.
DISCLAIMER: My ad follows. Feel free to skip :-)
Regarding the translation of resources, the management of translations and the creation of resource DLLs, you may want to check out appTranslator.
END OF AD :-)
Regarding Unicode, MFC ships with ANSI and Unicode versions of the code. It's up to you to choose if you want to build an ANSI or a Unicode app: Just make your pick in the first page of project settings. Of course, if you are startgin from scratch, you should definitely go Unicode. But if legacy reasons force you to stay ANSI/MBCS, don't worry to much: It won't prevent you from localizing your app.
Years ago when I had to work with multiple languages in MFC, we used separate resource DLLs. All you need do is make one call to switch which handle the resource functions would use and all was automatic from that point forward.
You need to do more than just change the strings. Dialogs in particular will have strings inside of them, and you may need to change the layout if those strings become too long after translation.

C++ vim IDE. Things you'd need from it

I was going to create the C++ IDE Vim extendable plugin. It is not a problem to make one which will satisfy my own needs.
This plugin was going to work with workspaces, projects and its dependencies.
This is for unix like system with gcc as c++ compiler.
So my question is what is the most important things you'd need from an IDE? Please take in account that this is Vim, where almost all, almost, is possible.
Several questions:
How often do you manage different workspaces with projects inside them and their relationships between them? What is the most annoying things in this process.
Is is necessary to recreate "project" from the Makefile?
Thanks.
Reason to create this plugin:
With a bunch of plugins and self written ones we can simulate most of things. It is ok when we work on a one big "infinitive" project.
Good when we already have a makefile or jam file. Bad when we have to create our owns, mostly by copy and paste existing.
All ctags and cscope related things have to know about list of a real project files. And we create such ones. This <project#get_list_of_files()> and many similar could be a good project api function to cooperate with an existing and the future plugins.
Cooperation with an existing makefiles can help to find out the list of the real project files and the executable name.
With plugin system inside the plugin there can be different project templates.
Above are some reasons why I will start the job. I'd like to hear your one.
There are multiple problems. Most of them are already solved by independent and generic plugins.
Regarding the definition of what is a project.
Given a set of files in a same directory, each file can be the unique file of a project -- I always have a tests/ directory where I host pet projects, or where I test the behaviour of the compiler. On the opposite, the files from a set of directories can be part of a same and very big project.
In the end, what really defines a project is a (leaf) "makefile" -- And why restrict ourselves to makefiles, what about scons, autotools, ant, (b)jam, aap? And BTW, Sun-Makefiles or GNU-Makefiles ?
Moreover, I don't see any point in having vim know the exact files in the current project. And even so, the well known project.vim plugin already does the job. Personally I use a local_vimrc plugin (I'm maintaining one, and I've seen two others on SF). With this plugin, I just have to drop a _vimrc_local.vim file in a directory, and what is defined in it (:mappings, :functions, variables, :commands, :settings, ...) will apply to each file under the directory -- I work on a big project having a dozen of subcomponents, each component live in its own directory, has its own makefile (not even named Makefile, nor with a name of the directory)
Regarding C++ code understanding
Every time we want to do something complex (refactorings like rename-function, rename-variable, generate-switch-from-current-variable-which-is-an-enum, ...), we need vim to have an understanding of C++. Most of the existing plugins rely on ctags. Unfortunately, ctags comprehension of C++ is quite limited -- I have already written a few advanced things, but I'm often stopped by the poor information provided by ctags. cscope is no better. Eventually, I think we will have to integrate an advanced tool like elsa/pork/ionk/deshydrata/....
NB: That's where, now, I concentrate most of my efforts.
Regarding Doxygen
I don't known how difficult it is to jump to the doxygen definition associated to a current token. The first difficulty is to understand what the cursor is on (I guess omnicppcomplete has already done a lot of work in this direction). The second difficulty will be to understand how doxygen generate the page name for each symbol from the code.
Opening vim at the right line of code from a doxygen page should be simple with a greasemonkey plugin.
Regarding the debugger
There is the pyclewn project for those that run vim under linux, and with gdb as debugger. Unfortunately, it does not support other debuggers like dbx.
Responses to other requirements:
When I run or debug my compiled program, I'd like the option of having a dialog pop up which asks me for the command line parameters. It should remember the last 20 or so parameters I used for the project. I do not want to have to edit the project properties for this.
My BuildToolsWrapper plugin has a g:BTW_run_parameters option (easily overridden with project/local_vimrc solutions). Adding a mapping to ask the arguments to use is really simple. (see :h inputdialog())
work with source control system
There already exist several plugins addressing this issue. This has nothing to do with C++, and it must not be addressed by a C++ suite.
debugger
source code navigation tools (now I am using http://www.vim.org/scripts/script.php?script_id=1638 plugin and ctags)
compile lib/project/one source file from ide
navigation by files in project
work with source control system
easy acces to file changes history
rename file/variable/method functions
easy access to c++ help
easy change project settings (Makefiles, jam, etc)
fast autocomplette for paths/variables/methods/parameters
smart identation for new scopes (also it will be good thing if developer will have posibility to setup identation rules)
highlighting incorrect by code convenstion identation (tabs instead spaces, spaces after ";", spaces near "(" or ")", etc)
reformating selected block by convenstion
Things I'd like in an IDE that the ones I use don't provide:
When I run or debug my compiled program, I'd like the option of having a dialog pop up which asks me for the command line parameters. It should remember the last 20 or so parameters I used for the project. I do not want to have to edit the project properties for this.
A "Tools" menu that is configurable on a per-project basis
Ability to rejig the keyboard mappings for every possible command.
Ability to produce lists of project configurations in text form
Intelligent floating (not docked) windows for debugger etc. that pop up only when I need them, stay on top and then disappear when no longer needed.
Built-in code metrics analysis so I get a list of the most complex functions in the project and can click on them to jump to the code
Built-in support for Doxygen or similar so I can click in a Doxygen document and go directly to code. Sjould also reverse navigate from code to Doxygen.
No doubt someone will now say Eclipse can do this or that, but it's too slow and bloated for me.
Adding to Neil's answer:
integration with gdb as in emacs. I know of clewn, but I don't like that I have to restart vim to restart the debugger. With clewn, vim is integrated into the debugger, but not the other way around.
Not sure if you are developing on Windows, but if you are I suggest you check out Viemu. It is a pretty good VIM extension for Visual Studio. I really like Visual Studio as an IDE (although I still think VC6 is hard to beat), so a Vim extension for VS was perfect for me. Features that I would prefer worked better in a Vim IDE are:
The Macro Recording is a bit error prone, especially with indentation. I find I can easily and often record macros in Vim while I am editing code (eg. taking an enum defn from a header and cranking out a corresponding switch statement), but found that Viemu is a bit flakey in that deptartment.
The VIM code completion picks up words in the current buffer where Viemu hooks into the VS code completion stuff. This means if I have just created a method name and I want to ctrl ] to auto complete, Vim will pick it up, but Viemu won't.
For me, it's just down to the necessities
nice integration with ctags, so you can do jump to definition
intelligent completion, that also give you the function prototype
easy way to switch between code and headers
interactive debugging with breaakpoints, but maybe
maybe folding
extra bonus points for refactoring tools like rename or extract method
I'd say stay away from defining projects - just treat the entire file branch as part of the "project" and let users have a settings file to override that default
99% of the difference in speed I see between IDE and vim users is code lookup and navigation. You need to be able to grep your source tree for a phrase (or intelligently look for the right symbol using ctags), show all the hits, and switch to that file in like two or three keystrokes.
All the other crap like repository navigation or interactive debugging is nice, but there are other ways to solve those problems. I'd say drop the interactive debugging even. Just focus on what makes IDEs good editors - have a "big picture" view of your project, instead of single file.
In fact, are there any plugins for vim that already achieve this?

C++ Header files - put them in one directory or merged in a tree structure?

I have a substantial body of source code (OOFILE) which I'm finally putting up on Sourceforge. I need to decide if I should go with a monolithic include directory or keep the header files with the source tree.
I want to make this decision before pushing to the svn repo on SourceForge. I expect a lot of people who use it after that move will keep a working copy checked out directly from SF so won't want to change their structure.
The full source tree has about 262 files in 25 folders. There are a lot more classes than that suggests as due to conforming to 8.3 character names (yes it dates back to Win3.1) many classes are in one file. As I used to develop with ObjectMaster, that never bothered me but I will be splitting it up to conform to more recent trends to minimise the number of classes per file. From a quick skim of the class list, there are about 600 classes.
OOFILE is a cross-platform product expected to be built on Mac, Windows and assorted Unix platforms. As it started life on Mac, with compilers that point to include trees rather than flat include dirs, headers were kept with the source.
Later, mainly to keep some Visual Studio users happy, a build was reorganised with a single include directory. I'm trying to choose between those models.
The entire OOFILE product covers quite a few domains:
database front-end
range of database backends
simple 2D graphing engine for Mac and Windows
simple character-mode report-writer for trivial html and text listing
very rich banding report-writer with Mac and Windows Preview and Printing and cross-platform generation of text, RTF, HTML and XML reports
forms integration engine for easy CRUD forms binding to the database, with implementations on PowerPlant and MFC
cross-platform utility classes
file and directory manipulation
strings
arrays
XML and tag generation
Many people only want to use it on a single platform and some of those code areas are pure legacy (eg: PowerPlant UI framework on classic Mac). It therefore seems people would appreciate not having headers from those unwanted areas dumped in their monolithic include directory.
I started thinking about having an include directory split up into a few of the domains above and then realised that was sounding more like the original structure.
In summary, the choices seem to be:
Keep original model, all headers adjacent to source - max flexibility at cost of some complex includes in projects.
one include directory with everything inside
split includes by domain, so there may be about 6 directories for someone using the lot but a pure database user would probably have a single directory.
From a Unix build aspect, the recommended structure has been 2. My situation is complicated by needing to keep Visual Studio and XCode users happy (sniff, CodeWarrior, how I doth miss thee!).
Edit - the chosen solution:
I went with four subdirectories in include. I started trying to divide them up further by platform but it just got very noisy very quickly.
Personally I would go with 2, or 3 if really pushed.
But whichever you choose, please make it crystal clear in the build instructions how to set up the include paths. Nothing dooms an open source project more than it being really difficult to build - developers want a quick out-of-the-box experience and if it involves faffing around with many undocumented environment variables (or whatever) most will simply go away.