I would like to translate my installer wizard (Qt Installer Framework based) in English or French (OS language depends).
I added those lines in the "installscript.qs" file :
Component.prototype.retranslateUi = function()
{
component.languageChanged();
}
and I added those in "config.xml" file :
<Installer>
...
<Translations>
<Translation>fr.qm</Translation>
</Translations>
</Installer>
But everything is ok (all long texts are translated) (in French) but the buttons like "Next", "Cancel", "Quit" are not translated (see the screenshot) :
ps: I don't want to use C++ code. (only Script or Xml)
You need to load the Qt translation file in addition to your own .qm file(s). The file is located in the translation sub-folder of your Qt installation folder (e.g. ./usr/share/qt5/translations/). For some languages it seems sufficient to load qt_xx (where XX should be replaced with your locale), but for German I had to load "qtbase_XX" to translate the Next and Cancel buttons. In example for the fr locale they are named qt_fr.qm and qtbase_fr.qm.
EDIT:
Because of the comment of John Smith I checked the Installer framework source and the framework is not capable loading more than one translation file:
See installer-framework/src/libs/installer/component.cpp
/*!
Loads the translations matching the name filters \a qms inside \a directory. Only translations
with a base name matching the current locale's name are loaded. For more information, see
\l{Translating Pages}.
*/
void Component::loadTranslations(const QDir &directory, const QStringList &qms)
So my original answer above (which would lead to a translated QWizard::CancelButton) is not working.
I got the Quit button of the Installer Frameworks translation example translated to German by correcting the de.ts file provided within the framworks source in installer-framework/src/sdk/translations
The original translation coming with the feramework is missing an &:
So, changing:
<context>
<name>QInstaller::IntroductionPage</name>
...
<message>
<source>Quit</source>
<translation>Beenden</translation>
</message>
to
<context>
<name>QInstaller::IntroductionPage</name>
...
<message>
<source>&Quit</source>
<translation>Beenden</translation>
</message>
and recompiling the Framework leads to a translated Quit button (Beenden) within the framework.
I did not tried, but studying /installer-framework/src/libs/installer/packagemanagergui.cpp should enable you to translate the Next button, too.
Adding a context may help:
function Component()
{
qsTranslate("QInstaller::IntroductionPage", "&Quit");
}
It woked after Next and Back, but could not find where to write the qsTranslate().
Related
I use Qt Installer Framework.
I want to know how to prevent installation in a non-empty folder?
In addition, how can I make the uninstaller remove only the files and folders it has installed, and not all the contents of its folder?
Thank you in advance
Due to the Qt Documentation you have access to the QDesktopServices inside the Scripting API, which contains the function findFiles(string path,string pattern), which should return none in your case, where path is your target directory for installation.
In the TargetDirectory Installer Installer Page you have access to the set TargetDirectory via Installer Page, which can be connected to if there is some edit.
It took me some hard time to figure out the following solution, which I have to admit is not the way I wanted to have it beforehand.
First of all you need a control script, that needs to be set inside your config.xml. It is called controlScript.js and resides in the same directory as your config.xml.
config.xml
<?xml version="1.0" encoding="UTF-8"?>
<Installer>
<Name>Your application</Name>
<Version>1.0.0</Version>
<Title>Your application Installer</Title>
<Publisher>Your vendor</Publisher>
<StartMenuDir>Super App</StartMenuDir>
<TargetDir>#HomeDir#/InstallationDirectory</TargetDir>
<ControlScript>controlScript.js</ControlScript>
</Installer>
Now, the only solution that I brought to work is the following:
controlScript.js
function Controller()
{
console.log("Control script");
}
Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget();
widget.title="Select empty directory!";
var targetDirWidget = gui.pageById(QInstaller.TargetDirectory);
var targetDir=targetDirWidget.TargetDirectoryLineEdit.text;
var files=QDesktopServices.findFiles(targetDir, "*.*");
if (files.length!=0) {
var result = QMessageBox.warning("quit.question", "You selected a non-empty directory!", targetDir,QMessageBox.Ok);
gui.clickButton(buttons.BackButton);
}
}
Basically, the user enters a target directory and presses the BackButton. In case the target directory is non-empty a message box is displayed and the BackButton in the Component Selection is pressed.
My desired solution was beforehand to deactivate the NextButton in the TargetDirectory Page, but all my attempts were futile. Even though the following disabling of the NextButton should work, as shown in this answer.
I want to change the language using QCoreApplication::installTranslator with a few different .qm files for every language (different parts of the project result in different .qm files).
It is fine to use more than one .qm file :
QCoreApplication::installTranslator(QTranslator *translationFile)
Multiple translation files can be installed. Translations are searched
for in the reverse order in which they were installed, so the most
recently installed translation file is searched first and the first
translation file installed is searched last.
But, if I do not remove the older translators, they are still candidates for translations. Even though they would be the less recently installed translators.
How can I clear any file loaded previously before loading the wanted ones ?
The only way I see is to keep the pointers I installed and remove them one by one when I want to change, but is there something more straightforward ?
I maintain a list of the installed translators :
// Install the translators
for (auto fileName : qAsConst(fileList)) {
auto translator = QSharedPointer<QTranslator>::create();
translator->load(fileName);
m_currentTranslators << translator;
QCoreApplication::installTranslator(translator.data());
}
And to remove them all :
for (auto translator : qAsConst(m_currentTranslators)) {
QCoreApplication::removeTranslator(translator.data());
}
m_currentTranslators.clear();
I'm making an application part of which is reading from an XML which stores some preferences. However, whenever I build the project, all the sources get copied but the preferences file does not! I have added the following to the .pro file -
RESOURCES += rsc.qrc
And my rsc.qrc contains
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>data/preferences.xml</file>
<file>data/gamedata.xml</file>
</qresource>
</RCC>
Now whenever I try to open preferences.xml
QFile preferences(":/data/preferences.xml");
if(!preferences.exists()){
preferences.open(QFile::WriteOnly);
preferences.write("abc");
qDebug() << "Written";
}
else {
qDebug() << "File exists";
}
Absolutely nothing gets printed and even the rest of the application stops working.
You don't use the resource part correctly in your example.
It will most likely not work because you try to write to a resource that is embedded into your executable after you have build your application. Reading is fine, but writing can't work by definition.
If you want a editable setting files, you have to distribute them along with your executable, or use a different method for reading/writing your settings like QSettings.
However using QSettings also means, that you will need to configure all your default settings in your loading function in case the values do not exist if you use the default configuration. Meaning you use registry on windows.
You have the option to force the use of a INI file format in the constructor of QSettings, this can make sense if you want to provide a default settings INI file instead of your xml files.
In case you want to store more complex data a xml file might be needed anyway, so if you want to stick with that you will need a way to copy your setting files to your build path. This can be done within your pro file with QMAKE_POST_LINK.
Example:
COPY_CMD = "$$PWD\\data\\preferences.xml $$OUT_PWD\\release\\data\\preferences.xml"
COPY_CMD = $${QMAKE_COPY} $$replace( COPY_CMD, "/", "\\" ) $$escape_expand( \\n\\t )
QMAKE_POST_LINK += $$COPY_CMD
Newly created files in Atom are always "Plain Text". How can I change this so that new files will automatically be in another language, for example "Shell Script (Bash)"? I want to do this because auto indentation does not work with Plain Text files.
Had this problem as well, there is a plugin called default-language that will do this for you.
Search atom for default-language, install and open its settings. Type the name of the language you want Atom to default to, e.g. Shell Script (if in doubt, copy from the language selection menu) in the Default Language field. Next time you open a script with no extension (or shebang) it'll default to the language you set.
The following code, added to your init.coffee, will do what you're asking:
atom.workspace.observeTextEditors (editor) ->
default_scope = 'source.shell'
original = editor.getGrammar()
# If the editor has "null" grammar (aka unset)
if original? and original is atom.grammars.grammarForScopeName('text.plain.null-grammar')
default_grammar = atom.grammars.grammarForScopeName(default_scope)
if default_grammar? # check if desired grammar is already loaded
editor.setGrammar(default_grammar)
else
# grammar was not loaded yet, so add a callback as grammars load
callback = atom.grammars.onDidAddGrammar (grammar) ->
if grammar.id is default_scope
# once we've loaded the grammar, set it and dispose of the callback
editor.setGrammar(grammar)
callback.dispose()
Things to note:
The init.coffee file is where you can customize Atom without having to write a package
The observeTextEditors method sets a callback that is called upon each TextEditor creation for currently open and future editors
The code above:
Checks the grammar that the editor was created with
If and only if it is the default ("null") grammar, it sets the editor's grammar to the Shell grammar once it's loaded
Disposes of the callback to check for grammar loading once it's done with it
This should solve the TypeError: Cannot call method 'getScore' of undefined that happens for the first file opened in a new window.
To default to a different grammar, just change the default_scope = 'source.shell' line to use the scope of whatever grammar you'd like.
Firstly, CTRL+SHIFT+L is your friend. It's unfortunately not a permanent solution, but nice to know about.
Of course, we'd prefer a more permanent solution. A couple of the other answers are now obsolete due to API changes in Atom. Below is a more up-to-date version. Inspiration initially came from this discussion, but the other answers here seem to follow the same concept as well.
Place this in your init.coffee file (File -> Open Your Init Script):
extname = require("path").extname
fileTypes =
".wxs": "text.xml"
".wxi": "text.xml"
".wixobj": "text.xml"
nullGrammar = atom.grammars.selectGrammar("text.plain.null-grammar")
atom.workspace.observeTextEditors (editor) ->
grammar = atom.grammars.selectGrammar(fileTypes[extname(editor.getPath())])
editor.setGrammar grammar if editor.getGrammar() is nullGrammar and grammar isnt nullGrammar
Basically, you define have an array of file types, and the grammars (AKA syntax highlighting) that you want to associate them with. Find each editor, find out if it has a selected grammar already, and if not, attempt to give it one if we find one.
The one issue I've had with this is that the syntax highlighting only works if you open files after you've already launched Atom; if you open a file that results in Atom launching (say by double clicking on it's icon in your favourite OS), syntax highlighting won't for that file until you re-open it.
You need to create a mapping in your config.cson file.
"*":
core:
customFileTypes:
"source.shell": [
"sh"
"shell"
]
For mapping .sh and .shell files to shell script syntax.
Have a look at this bit of code: (you can can then change 'text.html.basic' to whichever syntax you require)
editor = atom.workspace.getActiveTextEditor()
cursor = editor.getLastCursor()
valueAtCursor = atom.config.get(cursor.getScopeDescriptor(), 'my-package.my-setting')
valueForLanguage = atom.config.get(editor.getRootScopeDescriptor('text.html.basic'), 'my-package.my-setting')
For reference please see: Scope Descriptors # https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors
Using Qt 4.7.4 on Mac.
My *.TS files are generated and are UTF-8 using a perl script I wrote. Long story with legacy dependency. We have 13 languages we have to support including some exotic ones. Generating *.QM files out of them seems to work well. You can load the *.QM file into Qt Linguist and everything looks healthy.
Due to legacy reasons, my system langauge is “Enums”. That is, I do something like this:
QString label = tr("APP_STRINGS_MYLABEL_TEXT"); // this translates to 13 langauges...
so, an excerpt from the english .TS file for instance reads:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="en">
<defaultcodec>UTF-8</defaultcodec>
<context>
<name>MyApp</name>
<message>
<source>APP_STRINGS_MYLABEL_TEXT/source>
<translation>My Label Text In English</translation>
</message>
..
..
..
</context>
My project file has the following:
CODECFORTR = UTF-8
My main method has test code that looks like this:
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTranslator translator;
bool empty = translator.isEmpty(); // Returns TRUE
bool loaded = translator.load("myApp_en","/Users/user/Dev/myApp/translation");
empty = translator.isEmpty(); // returns FALSE
// install the translator.
MyApp->installTranslator(&translator);
// Here comes my problem...
QString test = MyApp->trUtf8("APP_STRINGS_MYLABEL_TEXT"); // returns "APP_STRINGS_MYLABEL_TEXT"
QString test2 = MyApp->tr("APP_STRINGS_MYLABEL_TEXT"); // returns "APP_STRINGS_MYLABEL_TEXT"
As you can see, all my strings are being translated back to their original values. No real translation takes place. If you have any idea why thins might be happening, i’d appreciate the assistance. I am at a loss right now.
The culprit was the context. Since I am using generated strings from a 3rd party source, the context was always wrong. As soon as I started using the "MyApp" context explicitly in the translate API it started working.
thanks to all those who responded.