Add scaffolding for translations. (#2612)

* Fix up concat strings in favor of args, remove some translations that are not meant to be translated and add chinese.

Signed-off-by: Adam Treat <treat.adam@gmail.com>
pull/2652/head
AT 2 months ago committed by GitHub
parent df5d374187
commit 607ac19dcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -44,9 +44,9 @@ configure_file(
)
if(LINUX)
find_package(Qt6 6.4 COMPONENTS Core Quick WaylandCompositor QuickDialogs2 Svg HttpServer Sql Pdf REQUIRED)
find_package(Qt6 6.4 COMPONENTS Core Quick WaylandCompositor QuickDialogs2 Svg HttpServer Sql Pdf LinguistTools REQUIRED)
else()
find_package(Qt6 6.4 COMPONENTS Core Quick QuickDialogs2 Svg HttpServer Sql Pdf REQUIRED)
find_package(Qt6 6.4 COMPONENTS Core Quick QuickDialogs2 Svg HttpServer Sql Pdf LinguistTools REQUIRED)
endif()
# Get the Qt6Core target properties
@ -226,6 +226,10 @@ qt_add_qml_module(chat
icons/you.svg
)
qt_add_translations(chat
TS_FILES ${CMAKE_SOURCE_DIR}/translations/gpt4all_en.ts
)
set_target_properties(chat PROPERTIES
WIN32_EXECUTABLE TRUE
)

@ -239,8 +239,8 @@ void Chat::newPromptResponsePair(const QString &prompt)
{
resetResponseState();
m_chatModel->updateCurrentResponse(m_chatModel->count() - 1, false);
m_chatModel->appendPrompt(tr("Prompt: "), prompt);
m_chatModel->appendResponse(tr("Response: "), prompt);
m_chatModel->appendPrompt("Prompt: ", prompt);
m_chatModel->appendResponse("Response: ", prompt);
emit resetResponseRequested();
}
@ -248,8 +248,8 @@ void Chat::serverNewPromptResponsePair(const QString &prompt)
{
resetResponseState();
m_chatModel->updateCurrentResponse(m_chatModel->count() - 1, false);
m_chatModel->appendPrompt(tr("Prompt: "), prompt);
m_chatModel->appendResponse(tr("Response: "), prompt);
m_chatModel->appendPrompt("Prompt: ", prompt);
m_chatModel->appendResponse("Response: ", prompt);
}
bool Chat::isRecalc() const

@ -17,6 +17,7 @@
#include <QQmlEngine>
#include <QSettings>
#include <QString>
#include <QTranslator>
#include <QUrl>
#include <Qt>
@ -31,6 +32,12 @@ int main(int argc, char *argv[])
Logger::globalInstance();
QGuiApplication app(argc, argv);
QTranslator translator;
bool success = translator.load(":/i18n/gpt4all_en.qm");
Q_ASSERT(success);
app.installTranslator(&translator);
QQmlApplicationEngine engine;
QString llmodelSearchPaths = QCoreApplication::applicationDirPath();

@ -20,7 +20,7 @@ Window {
minimumWidth: 1280
minimumHeight: 720
visible: true
title: qsTr("GPT4All v") + Qt.application.version
title: qsTr("GPT4All v%1").arg(Qt.application.version)
Settings {
property alias x: window.x
@ -108,14 +108,14 @@ Window {
shouldShowBusy: false
closePolicy: Popup.NoAutoClose
modal: true
text: qsTr("<h3>Encountered an error starting up:</h3><br>")
+ qsTr("<i>\"Incompatible hardware detected.\"</i>")
+ qsTr("<br><br>Unfortunately, your CPU does not meet the minimal requirements to run ")
+ qsTr("this program. In particular, it does not support AVX intrinsics which this ")
+ qsTr("program requires to successfully run a modern large language model. ")
+ qsTr("The only solution at this time is to upgrade your hardware to a more modern CPU.")
+ qsTr("<br><br>See here for more information: <a href=\"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions\">")
+ qsTr("https://en.wikipedia.org/wiki/Advanced_Vector_Extensions</a>")
text: qsTr("<h3>Encountered an error starting up:</h3><br>"
+ "<i>\"Incompatible hardware detected.\"</i>"
+ "<br><br>Unfortunately, your CPU does not meet the minimal requirements to run "
+ "this program. In particular, it does not support AVX intrinsics which this "
+ "program requires to successfully run a modern large language model. "
+ "The only solution at this time is to upgrade your hardware to a more modern CPU."
+ "<br><br>See here for more information: <a href=\"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions\">"
+ "https://en.wikipedia.org/wiki/Advanced_Vector_Extensions</a>");
}
PopupDialog {
@ -124,12 +124,12 @@ Window {
shouldTimeOut: false
shouldShowBusy: false
modal: true
text: qsTr("<h3>Encountered an error starting up:</h3><br>")
+ qsTr("<i>\"Inability to access settings file.\"</i>")
+ qsTr("<br><br>Unfortunately, something is preventing the program from accessing ")
+ qsTr("the settings file. This could be caused by incorrect permissions in the local ")
+ qsTr("app config directory where the settings file is located. ")
+ qsTr("Check out our <a href=\"https://discord.gg/4M2QFmTt2k\">discord channel</a> for help.")
text: qsTr("<h3>Encountered an error starting up:</h3><br>"
+ "<i>\"Inability to access settings file.\"</i>"
+ "<br><br>Unfortunately, something is preventing the program from accessing "
+ "the settings file. This could be caused by incorrect permissions in the local "
+ "app config directory where the settings file is located. "
+ "Check out our <a href=\"https://discord.gg/4M2QFmTt2k\">discord channel</a> for help.")
}
StartupDialog {

@ -1553,7 +1553,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>OpenAI's ChatGPT model GPT-3.5 Turbo</strong><br>") + chatGPTDesc },
tr("<strong>OpenAI's ChatGPT model GPT-3.5 Turbo</strong><br> %1").arg(chatGPTDesc) },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "ca" },
{ ModelList::RamrequiredRole, 0 },
@ -1581,7 +1581,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>OpenAI's ChatGPT model GPT-4</strong><br>") + chatGPTDesc + chatGPT4Warn },
tr("<strong>OpenAI's ChatGPT model GPT-4</strong><br> %1 %2").arg(chatGPTDesc).arg(chatGPT4Warn) },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "cb" },
{ ModelList::RamrequiredRole, 0 },
@ -1612,7 +1612,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>Mistral Tiny model</strong><br>") + mistralDesc },
tr("<strong>Mistral Tiny model</strong><br> %1").arg(mistralDesc) },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "cc" },
{ ModelList::RamrequiredRole, 0 },
@ -1637,7 +1637,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>Mistral Small model</strong><br>") + mistralDesc },
tr("<strong>Mistral Small model</strong><br> %1").arg(mistralDesc) },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "cd" },
{ ModelList::RamrequiredRole, 0 },
@ -1663,7 +1663,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>Mistral Medium model</strong><br>") + mistralDesc },
tr("<strong>Mistral Medium model</strong><br> %1").arg(mistralDesc) },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "ce" },
{ ModelList::RamrequiredRole, 0 },

@ -94,7 +94,7 @@ Rectangle {
function onDiscoverInProgressChanged() {
if (ModelList.discoverInProgress) {
discoverField.textBeingSearched = discoverField.text;
discoverField.text = qsTr("Searching \u00B7 ") + discoverField.textBeingSearched;
discoverField.text = qsTr("Searching \u00B7 %1").arg(discoverField.textBeingSearched);
} else {
discoverField.text = discoverField.textBeingSearched;
discoverField.textBeingSearched = "";
@ -190,7 +190,7 @@ Rectangle {
rightPadding: 30
color: theme.textColor
text: {
return qsTr("Sort by: ") + comboSort.displayText
return qsTr("Sort by: %1").arg(comboSort.displayText)
}
font.pixelSize: theme.fontSizeLarger
verticalAlignment: Text.AlignVCenter
@ -215,7 +215,7 @@ Rectangle {
rightPadding: 30
color: theme.textColor
text: {
return qsTr("Sort dir: ") + comboSortDirection.displayText
return qsTr("Sort dir: %1").arg(comboSortDirection.displayText)
}
font.pixelSize: theme.fontSizeLarger
verticalAlignment: Text.AlignVCenter
@ -251,7 +251,7 @@ Rectangle {
rightPadding: 30
color: theme.textColor
text: {
return qsTr("Limit: ") + comboLimit.displayText
return qsTr("Limit: %1").arg(comboLimit.displayText)
}
font.pixelSize: theme.fontSizeLarger
verticalAlignment: Text.AlignVCenter
@ -284,7 +284,7 @@ Rectangle {
Layout.fillHeight: true
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
text: qsTr("Network error: could not retrieve http://gpt4all.io/models/models3.json")
text: qsTr("Network error: could not retrieve %1").arg("http://gpt4all.io/models/models3.json")
font.pixelSize: theme.fontSizeLarge
color: theme.mutedTextColor
}
@ -454,9 +454,7 @@ Rectangle {
Layout.leftMargin: 20
visible: downloadError !== ""
textFormat: Text.StyledText
text: "<strong><font size=\"1\">"
+ qsTr("<a href=\"#error\">Error</a>")
+ "</strong></font>"
text: qsTr("<strong><font size=\"1\"><a href=\"#error\">Error</a></strong></font>")
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
linkColor: theme.textErrorColor
@ -475,10 +473,7 @@ Rectangle {
Layout.leftMargin: 20
Layout.maximumWidth: 300
textFormat: Text.StyledText
text: qsTr("<strong><font size=\"2\">WARNING: Not recommended for your hardware.")
+ qsTr(" Model requires more memory (") + ramrequired
+ qsTr(" GB) than your system has available (")
+ LLM.systemTotalRAMInGBString() + ").</strong></font>"
text: qsTr("<strong><font size=\"2\">WARNING: Not recommended for your hardware. Model requires more memory (%1 GB) than your system has available (%2).</strong></font>").arg(ramrequired).arg(LLM.systemTotalRAMInGBString())
color: theme.textErrorColor
font.pixelSize: theme.fontSizeLarge
wrapMode: Text.WordWrap
@ -630,7 +625,7 @@ Rectangle {
color: theme.mutedDarkTextColor
}
Text {
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
text: ramrequired >= 0 ? qsTr("%1 GB").arg(ramrequired) : qsTr("?")
color: theme.textColor
font.pixelSize: theme.fontSizeSmall
font.bold: true
@ -652,7 +647,7 @@ Rectangle {
color: theme.mutedDarkTextColor
}
Text {
text: parameters !== "" ? parameters : "?"
text: parameters !== "" ? parameters : qsTr("?")
color: theme.textColor
font.pixelSize: theme.fontSizeSmall
font.bold: true

@ -55,18 +55,18 @@ Rectangle {
id: modelLoadingErrorPopup
anchors.centerIn: parent
shouldTimeOut: false
text: qsTr("<h3>Encountered an error loading model:</h3><br>")
+ "<i>\"" + currentChat.modelLoadingError + "\"</i>"
+ qsTr("<br><br>Model loading failures can happen for a variety of reasons, but the most common "
+ "causes include a bad file format, an incomplete or corrupted download, the wrong file "
+ "type, not enough system RAM or an incompatible model type. Here are some suggestions for resolving the problem:"
+ "<br><ul>"
+ "<li>Ensure the model file has a compatible format and type"
+ "<li>Check the model file is complete in the download folder"
+ "<li>You can find the download folder in the settings dialog"
+ "<li>If you've sideloaded the model ensure the file is not corrupt by checking md5sum"
+ "<li>Read more about what models are supported in our <a href=\"https://docs.gpt4all.io/\">documentation</a> for the gui"
+ "<li>Check out our <a href=\"https://discord.gg/4M2QFmTt2k\">discord channel</a> for help")
text: qsTr("<h3>Encountered an error loading model:</h3><br>"
+ "<i>\"%1\"</i>"
+ "<br><br>Model loading failures can happen for a variety of reasons, but the most common "
+ "causes include a bad file format, an incomplete or corrupted download, the wrong file "
+ "type, not enough system RAM or an incompatible model type. Here are some suggestions for resolving the problem:"
+ "<br><ul>"
+ "<li>Ensure the model file has a compatible format and type"
+ "<li>Check the model file is complete in the download folder"
+ "<li>You can find the download folder in the settings dialog"
+ "<li>If you've sideloaded the model ensure the file is not corrupt by checking md5sum"
+ "<li>Read more about what models are supported in our <a href=\"https://docs.gpt4all.io/\">documentation</a> for the gui"
+ "<li>Check out our <a href=\"https://discord.gg/4M2QFmTt2k\">discord channel</a> for help").arg(currentChat.modelLoadingError);
}
PopupDialog {
@ -107,7 +107,7 @@ Rectangle {
for (var i = 0; i < chatModel.count; i++) {
var item = chatModel.get(i)
var string = item.name;
var isResponse = item.name === qsTr("Response: ")
var isResponse = item.name === "Response: "
string += chatModel.get(i).value
if (isResponse && item.stopped)
string += " <stopped>"
@ -121,7 +121,7 @@ Rectangle {
var str = "{\"conversation\": [";
for (var i = 0; i < chatModel.count; i++) {
var item = chatModel.get(i)
var isResponse = item.name === qsTr("Response: ")
var isResponse = item.name === "Response: "
str += "{\"content\": ";
str += JSON.stringify(item.value)
str += ", \"role\": \"" + (isResponse ? "assistant" : "user") + "\"";
@ -374,9 +374,9 @@ Rectangle {
if (!currentModelInstalled())
return qsTr("Not found: %1").arg(currentModelName())
if (currentChat.modelLoadingPercentage === 0.0)
return qsTr("Reload \u00B7 ") + currentModelName()
return qsTr("Reload \u00B7 %1").arg(currentModelName())
if (currentChat.isCurrentlyLoading)
return qsTr("Loading \u00B7 ") + currentModelName()
return qsTr("Loading \u00B7 %1").arg(currentModelName())
return currentModelName()
}
font.pixelSize: theme.fontSizeLarger
@ -705,7 +705,7 @@ Rectangle {
}
}
text: qsTr("Load \u00B7 ") + defaultModel + qsTr(" (default) \u2192");
text: qsTr("Load \u00B7 %1 (default) \u2192").arg(defaultModel);
onClicked: {
var i = comboBox.find(MySettings.userDefaultModel)
if (i !== -1) {
@ -812,7 +812,7 @@ Rectangle {
fillMode: Image.PreserveAspectFit
mipmap: true
visible: false
source: name !== qsTr("Response: ") ? "qrc:/gpt4all/icons/you.svg" : "qrc:/gpt4all/icons/gpt4all_transparent.svg"
source: name !== "Response: " ? "qrc:/gpt4all/icons/you.svg" : "qrc:/gpt4all/icons/gpt4all_transparent.svg"
}
ColorOverlay {
@ -845,7 +845,7 @@ Rectangle {
anchors.bottom: parent.bottom
TextArea {
text: name === qsTr("Response: ") ? qsTr("GPT4All") : qsTr("You")
text: name === "Response: " ? qsTr("GPT4All") : qsTr("You")
padding: 0
font.pixelSize: theme.fontSizeLarger
font.bold: true
@ -855,7 +855,7 @@ Rectangle {
readOnly: true
}
Text {
visible: name === qsTr("Response: ")
visible: name === "Response: "
font.pixelSize: theme.fontSizeLarger
text: currentModelName()
color: theme.mutedTextColor
@ -870,8 +870,8 @@ Rectangle {
return qsTr("recalculating context ...");
switch (currentChat.responseState) {
case Chat.ResponseStopped: return qsTr("response stopped ...");
case Chat.LocalDocsRetrieval: return qsTr("retrieving localdocs: ") + currentChat.collectionList.join(", ") + " ...";
case Chat.LocalDocsProcessing: return qsTr("searching localdocs: ") + currentChat.collectionList.join(", ") + " ...";
case Chat.LocalDocsRetrieval: return qsTr("retrieving localdocs: %1 ...").arg(currentChat.collectionList.join(", "));
case Chat.LocalDocsProcessing: return qsTr("searching localdocs: %1 ...").arg(currentChat.collectionList.join(", "));
case Chat.PromptProcessing: return qsTr("processing ...")
case Chat.ResponseGeneration: return qsTr("generating response ...");
case Chat.GeneratingQuestions: return qsTr("generating questions ...");
@ -1005,7 +1005,7 @@ Rectangle {
Accessible.role: Accessible.Paragraph
Accessible.name: text
Accessible.description: name === qsTr("Response: ") ? "The response by the model" : "The prompt by the user"
Accessible.description: name === "Response: " ? "The response by the model" : "The prompt by the user"
}
ThumbsDownDialog {
@ -1031,7 +1031,7 @@ Rectangle {
Column {
Layout.alignment: Qt.AlignRight
Layout.rightMargin: 15
visible: name === qsTr("Response: ") &&
visible: name === "Response: " &&
(!currentResponse || !currentChat.responseInProgress) && MySettings.networkIsActive
spacing: 10
@ -1692,7 +1692,7 @@ Rectangle {
var listElement = chatModel.get(index);
currentChat.regenerateResponse()
if (chatModel.count) {
if (listElement.name === qsTr("Response: ")) {
if (listElement.name === "Response: ") {
chatModel.updateCurrentResponse(index, true);
chatModel.updateStopped(index, false);
chatModel.updateThumbsUpState(index, false);
@ -1766,7 +1766,7 @@ Rectangle {
padding: 15
topPadding: 8
bottomPadding: 8
text: qsTr("Reload \u00B7 ") + currentChat.modelInfo.name
text: qsTr("Reload \u00B7 %1").arg(currentChat.modelInfo.name)
fontPixelSize: theme.fontSizeSmall
Accessible.description: qsTr("Reloads the model")
}

@ -250,9 +250,7 @@ Rectangle {
Layout.leftMargin: 20
visible: downloadError !== ""
textFormat: Text.StyledText
text: "<strong><font size=\"1\">"
+ qsTr("<a href=\"#error\">Error</a>")
+ "</strong></font>"
text: qsTr("<strong><font size=\"1\"><a href=\"#error\">Error</a></strong></font>")
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
linkColor: theme.textErrorColor
@ -271,10 +269,7 @@ Rectangle {
Layout.leftMargin: 20
Layout.maximumWidth: 300
textFormat: Text.StyledText
text: qsTr("<strong><font size=\"2\">WARNING: Not recommended for your hardware.")
+ qsTr(" Model requires more memory (") + ramrequired
+ qsTr(" GB) than your system has available (")
+ LLM.systemTotalRAMInGBString() + ").</strong></font>"
text: qsTr("<strong><font size=\"2\">WARNING: Not recommended for your hardware. Model requires more memory (%1 GB) than your system has available (%2).</strong></font>").arg(ramrequired).arg(LLM.systemTotalRAMInGBString())
color: theme.textErrorColor
font.pixelSize: theme.fontSizeLarge
wrapMode: Text.WordWrap
@ -426,7 +421,7 @@ Rectangle {
color: theme.mutedDarkTextColor
}
Text {
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
text: ramrequired >= 0 ? qsTr("%1 GB").arg(ramrequired) : qsTr("?")
color: theme.textColor
font.pixelSize: theme.fontSizeSmall
font.bold: true

@ -64,10 +64,7 @@ MyDialog {
id: welcome
width: 1024 - 40
textFormat: TextEdit.MarkdownText
text: qsTr("### Release notes\n")
+ Download.releaseInfo.notes
+ qsTr("### Contributors\n")
+ Download.releaseInfo.contributors
text: qsTr("### Release notes\n%1### Contributors\n%2").arg(Download.releaseInfo.notes).arg(Download.releaseInfo.contributors)
focus: false
readOnly: true
Accessible.role: Accessible.Paragraph

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save