Added translation folder + updated strings for translations

This commit is contained in:
Paul Ebbers 2025-01-10 19:22:33 +01:00
parent adc14d0155
commit 718401b049
10 changed files with 353 additions and 18 deletions

View File

@ -1,8 +1,14 @@
import FreeCAD as App
import FreeCADGui as Gui
globalGroups = []
itemGroups = None
serializedItemGroups = None
# Define the translation
translate = App.Qt.translate
def onResultSelected(index, groupId):
global globalGroups
@ -17,8 +23,11 @@ def onResultSelected(index, groupId):
QtGui.QMessageBox.warning(
None,
"Could not execute this action",
"Could not execute this action, it could be from a Mod that has been uninstalled. Try refreshing the list of tools.",
translate("SearchBar", "Could not execute this action"),
translate(
"SearchBar",
"Could not execute this action, it could be from a Mod that has been uninstalled. Try refreshing the list of tools.",
),
)
@ -31,7 +40,10 @@ def getToolTip(groupId, setParent):
if handlerName in SearchResults.toolTipHandlers:
return SearchResults.toolTipHandlers[handlerName](nfo, setParent)
else:
return "Could not load tooltip for this tool, it could be from a Mod that has been uninstalled. Try refreshing the list of tools."
return translate(
"SearchBar",
"Could not load tooltip for this tool, it could be from a Mod that has been uninstalled. Try refreshing the list of tools.",
)
def getItemGroups():

View File

@ -1,9 +1,20 @@
import FreeCAD as App
import FreeCADGui as Gui
# Avoid garbage collection by storing the action in a global variable
wax = None
sea = None
tbr = None
def QT_TRANSLATE_NOOP(context, text):
return text
# Define the translation
translate = App.Qt.translate
def addToolSearchBox():
import FreeCADGui
from PySide import QtGui
@ -24,9 +35,13 @@ def addToolSearchBox():
if wax is None:
wax = QtGui.QWidgetAction(None)
wax.setWhatsThis("Use this search bar to find tools, document objects, preferences and more")
wax.setWhatsThis(
translate("SearchBar", "Use this search bar to find tools, document objects, preferences and more")
)
sea.setWhatsThis("Use this search bar to find tools, document objects, preferences and more")
sea.setWhatsThis(
translate("SearchBar", "Use this search bar to find tools, document objects, preferences and more")
)
wax.setDefaultWidget(sea)
##mbr.addWidget(sea)
# mbr.addAction(wax)

View File

@ -1,17 +1,20 @@
import os
import FreeCAD as App
# Define the translation
translate = App.Qt.translate
def loadAllWorkbenches():
from PySide import QtGui
import FreeCADGui
activeWorkbench = FreeCADGui.activeWorkbench().name()
lbl = QtGui.QLabel("Loading workbench … (…/…)")
lbl = QtGui.QLabel(translate("SearchBar", "Loading workbench … (…/…)"))
lbl.show()
lst = FreeCADGui.listWorkbenches()
for i, wb in enumerate(lst):
msg = "Loading workbench " + wb + " (" + str(i) + "/" + str(len(lst)) + ")"
msg = translate("SearchBar", "Loading workbench ") + wb + " (" + str(i) + "/" + str(len(lst)) + ")"
print(msg)
lbl.setText(msg)
geo = lbl.geometry()
@ -88,8 +91,11 @@ def refreshToolsAction():
fw.clearFocus()
reply = QtGui.QMessageBox.question(
None,
"Load all workbenches?",
'Load all workbenches? This can cause FreeCAD to become unstable, and this "reload tools" feature contained a bug that crashed freecad systematically, so please make sure you save your work before. It\'s a good idea to restart FreeCAD after this operation.',
translate("SearchBar", "Load all workbenches?"),
translate(
"SearchBar",
'Load all workbenches? This can cause FreeCAD to become unstable, and this "reload tools" feature contained a bug that crashed freecad systematically, so please make sure you save your work before. It\'s a good idea to restart FreeCAD after this operation.',
),
QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No,
)

View File

@ -5,6 +5,9 @@ import FreeCADGui
import SafeViewer
import SearchBox
# Define the translation
translate = App.Qt.translate
def documentAction(nfo):
act = nfo["action"]

View File

@ -1,3 +1,6 @@
import FreeCAD as App
import FreeCADGui as Gui
import os
from PySide import QtGui
import Serialize_SearchBar
@ -5,6 +8,9 @@ import Parameters_SearchBar as Parameters
genericToolIcon = QtGui.QIcon(QtGui.QIcon(Parameters.genericToolIcon_Pixmap))
# Define the translation
translate = App.Qt.translate
def refreshToolsAction(nfo):
import RefreshTools
@ -15,7 +21,12 @@ def refreshToolsAction(nfo):
def refreshToolsToolTip(nfo, setParent):
return (
Serialize_SearchBar.iconToHTML(genericToolIcon)
+ "<p>Load all workbenches to refresh this list of tools. This may take a minute, depending on the number of installed workbenches.</p>"
+ "<p>"
+ translate(
"SearchBar",
"Load all workbenches to refresh this list of tools. This may take a minute, depending on the number of installed workbenches.",
)
+ "</p>"
)

View File

@ -1,7 +1,11 @@
import FreeCAD as App
from PySide import QtGui
import FreeCADGui
import Serialize_SearchBar
# Define the translation
translate = App.Qt.translate
def toolbarAction(nfo):
act = nfo["action"]

View File

@ -1,5 +1,8 @@
from PySide import QtGui
import FreeCAD
import FreeCAD as App
# Define the translation
translate = App.Qt.translate
class SafeViewer(QtGui.QWidget):
@ -7,7 +10,7 @@ class SafeViewer(QtGui.QWidget):
FreeCAD's FreeCADGui.createViewer() puts the viewer widget inside an MDI window, and detaching it without causing segfaults on exit is tricky.
This class contains some kludges to extract the viewer as a standalone widget and destroy it safely."""
enabled = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/SearchBar").GetBool("PreviewEnabled", False)
enabled = App.ParamGet("User parameter:BaseApp/Preferences/Mod/SearchBar").GetBool("PreviewEnabled", False)
instances = []
def __init__(self, parent=None):
@ -27,11 +30,18 @@ class SafeViewer(QtGui.QWidget):
self.lbl_warning.setReadOnly(True)
self.lbl_warning.setAlignment(QtCore.Qt.AlignTop)
self.lbl_warning.setText(
"Warning: the 3D preview has some stability issues. It can cause FreeCAD to crash (usually when quitting the application) and could in theory cause data loss, inside and outside of FreeCAD."
translate(
"SearchBar",
"Warning: the 3D preview has some stability issues. It can cause FreeCAD to crash (usually when quitting the application) and could in theory cause data loss, inside and outside of App.",
)
)
self.btn_enable_for_this_session = QtGui.QPushButton(
translate("SearchBar", "Enable 3D preview for this session")
)
self.btn_enable_for_this_session = QtGui.QPushButton("Enable 3D preview for this session")
self.btn_enable_for_this_session.clicked.connect(self.enable_for_this_session)
self.btn_enable_for_future_sessions = QtGui.QPushButton("Enable 3D preview for future sessions")
self.btn_enable_for_future_sessions = QtGui.QPushButton(
translate("SearchBar", "Enable 3D preview for future sessions")
)
self.btn_enable_for_future_sessions.clicked.connect(self.enable_for_future_sessions)
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(self.lbl_warning)
@ -46,7 +56,7 @@ class SafeViewer(QtGui.QWidget):
def enable_for_future_sessions(self):
if not SafeViewer.enabled:
# Store in prefs
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/SearchBar").SetBool("PreviewEnabled", True)
App.ParamGet("User parameter:BaseApp/Preferences/Mod/SearchBar").SetBool("PreviewEnabled", True)
# Then enable as usual
self.enable_for_this_session()

View File

@ -1,4 +1,5 @@
import FreeCADGui as Gui # just used for FreeCADGui.updateGui()
import FreeCAD as App
import FreeCADGui as Gui
import os
from PySide.QtCore import (
@ -44,6 +45,9 @@ genericToolIcon = QIcon(Parameters.genericToolIcon_Pixmap)
globalIgnoreFocusOut = False
# Define the translation
translate = App.Qt.translate
def easyToolTipWidget(html):
foo = QTextEdit()
@ -170,7 +174,7 @@ class SearchBox(QLineEdit):
mdl = QStandardItemModel()
mdl.appendRow(
[
QStandardItem(genericToolIcon, "Please wait, loading results from cache…"),
QStandardItem(genericToolIcon, translate("SearchBar", "Please wait, loading results from cache…")),
QStandardItem("0"),
QStandardItem("-1"),
]

104
translations/README.md Normal file
View File

@ -0,0 +1,104 @@
# About translating Ribbon Addon
> [!NOTE]
> All commands **must** be run in `./translations/` directory.
> [!IMPORTANT]
> If you want to update/release the files you need to have installed
> `lupdate` and `lrelease` from Qt6 version. Using the versions from
> Qt5 is not advised because they're buggy.
## Updating translations template file
To update the template file from source files you should use this command:
```shell
./update_translation.sh -U
```
Once done you can commit the changes and upload the new file to CrowdIn platform
at <https://crowdin.com/project/freecad-addons> webpage and find the **Ribbon** project.
## Creating file for missing locale
### Using script
To create a file for a new language with all **Ribbon** translatable strings execute
the script with `-u` flag plus your locale:
```shell
./update_translation.sh -u de
```
### Renaming file
Also you can rename new `SearchBar.ts` file by appending the locale code,
for example, `SearchBar_de.ts` for German and change
```xml
<TS version="2.1">
```
to
```xml
<TS version="2.1" language="de" sourcelanguage="en">
```
As of 2024/10/28 the supported locales on FreeCAD
(according to `FreeCADGui.supportedLocales()`) are 44:
```python
{'English': 'en', 'Afrikaans': 'af', 'Arabic': 'ar', 'Basque': 'eu',
'Belarusian': 'be', 'Bulgarian': 'bg', 'Catalan': 'ca',
'Chinese Simplified': 'zh-CN', 'Chinese Traditional': 'zh-TW', 'Croatian': 'hr',
'Czech': 'cs', 'Danish': 'da', 'Dutch': 'nl', 'Filipino': 'fil', 'Finnish': 'fi',
'French': 'fr', 'Galician': 'gl', 'Georgian': 'ka', 'German': 'de', 'Greek': 'el',
'Hungarian': 'hu', 'Indonesian': 'id', 'Italian': 'it', 'Japanese': 'ja',
'Kabyle': 'kab', 'Korean': 'ko', 'Lithuanian': 'lt', 'Norwegian': 'no',
'Polish': 'pl', 'Portuguese': 'pt-PT', 'Portuguese, Brazilian': 'pt-BR',
'Romanian': 'ro', 'Russian': 'ru', 'Serbian': 'sr', 'Serbian, Latin': 'sr-CS',
'Slovak': 'sk', 'Slovenian': 'sl', 'Spanish': 'es-ES', 'Spanish, Argentina': 'es-AR',
'Swedish': 'sv-SE', 'Turkish': 'tr', 'Ukrainian': 'uk', 'Valencian': 'val-ES',
'Vietnamese': 'vi'}
```
## Translating
To edit your language file open your file in `Qt Linguist` from `qt5-tools`/`qt6-tools`
package or in a text editor like `xed`, `mousepad`, `gedit`, `nano`, `vim`/`nvim`,
`geany` etc. and translate it.
Alternatively you can visit the **FreeCAD-addons** project on CrowdIn platform
at <https://crowdin.com/project/freecad-addons> webpage and find your language,
once done, look for the **Ribbon** project.
## Compiling translations
To convert all `.ts` files to `.qm` files (merge) you can use this command:
```shell
./update_translation.sh -R
```
If you are a translator that wants to update only their language file
to test it on **FreeCAD** before doing a PR you can use this command:
```shell
./update_translation.sh -r de
```
This will update the `.qm` file for your language (German in this case).
## Sending translations
Now you can contribute your translated `.ts` file to **Ribbon** repository,
also include the `.qm` file.
<https://github.com/APEbbers/FreeCAD-Ribbon>
## More information
You can read more about translating external workbenches here:
<https://wiki.freecad.org/Translating_an_external_workbench>

View File

@ -0,0 +1,166 @@
#!/usr/bin/env bash
# --------------------------------------------------------------------------------------------------
#
# Create, update and release translation files.
#
# Supported locales on FreeCAD <2024-10-14, FreeCADGui.supportedLocales(), total=44>:
# {'English': 'en', 'Afrikaans': 'af', 'Arabic': 'ar', 'Basque': 'eu', 'Belarusian': 'be',
# 'Bulgarian': 'bg', 'Catalan': 'ca', 'Chinese Simplified': 'zh-CN',
# 'Chinese Traditional': 'zh-TW', 'Croatian': 'hr', 'Czech': 'cs', 'Danish': 'da',
# 'Dutch': 'nl', 'Filipino': 'fil', 'Finnish': 'fi', 'French': 'fr', 'Galician': 'gl',
# 'Georgian': 'ka', 'German': 'de', 'Greek': 'el', 'Hungarian': 'hu', 'Indonesian': 'id',
# 'Italian': 'it', 'Japanese': 'ja', 'Kabyle': 'kab', 'Korean': 'ko', 'Lithuanian': 'lt',
# 'Norwegian': 'no', 'Polish': 'pl', 'Portuguese': 'pt-PT', 'Portuguese, Brazilian': 'pt-BR',
# 'Romanian': 'ro', 'Russian': 'ru', 'Serbian': 'sr', 'Serbian, Latin': 'sr-CS', 'Slovak': 'sk',
# 'Slovenian': 'sl', 'Spanish': 'es-ES', 'Spanish, Argentina': 'es-AR', 'Swedish': 'sv-SE',
# 'Turkish': 'tr', 'Ukrainian': 'uk', 'Valencian': 'val-ES', 'Vietnamese': 'vi'}
#
# NOTE: PREPARATION
# - Install Qt tools
# Debian-based (e.g., Ubuntu): $ sudo apt-get install qttools5-dev-tools pyqt6-dev-tools
# Fedora-based: $ sudo dnf install qt6-linguist qt6-devel
# Arch-based: $ sudo pacman -S qt6-tools python-pyqt6
# - Make the script executable
# $ chmod +x update_translation.sh
# - The script has to be executed within the `translations` directory.
# Executing the script with no flags invokes the help.
# $ ./update_translation.sh
#
# NOTE: WORKFLOW TRANSLATOR (LOCAL)
# - Execute the script passing the `-u` flag plus locale code as argument
# Only update the file(s) you're translating!
# $ ./update_translation.sh -u es-ES
# - Do the translation via Qt Linguist and use `File>Release`
# - If releasing with the script execute it passing the `-r` flag
# plus locale code as argument
# $ ./update_translation.sh -r es-ES
#
# NOTE: WORKFLOW MAINTAINER (CROWDIN)
# - Execute the script passing the '-U' flag
# $ ./update_translation.sh -U
# - Once done, download the translated files, copy them to `translations`
# - Upload the updated file to CrowdIn and wait for translators do their thing ;-)
# and release all the files to update the changes
# $ ./update_translation.sh -R
#
# --------------------------------------------------------------------------------------------------
supported_locales=(
"en" "af" "ar" "eu" "be" "bg" "ca" "zh-CN" "zh-TW" "hr"
"cs" "da" "nl" "fil" "fi" "fr" "gl" "ka" "de" "el"
"hu" "id" "it" "ja" "kab" "ko" "lt" "no" "pl" "pt-PT"
"pt-BR" "ro" "ru" "sr" "sr-CS" "sk" "sl" "es-ES" "es-AR" "sv-SE"
"tr" "uk" "val-ES" "vi"
)
is_locale_supported() {
local locale="$1"
for supported_locale in "${supported_locales[@]}"; do
[ "$supported_locale" == "$locale" ] && return 0
done
return 1
}
update_locale() {
local locale="$1"
local u=${locale:+_} # Conditional underscore
FILES="../*.py ../Resources/ui/*.ui"
# NOTE: Execute the right commands depending on:
# - if it's a locale file or the main, agnostic one
[ ! -f "${WB}${u}${locale}.ts" ] && action="Creating" || action="Updating"
echo -e "\033[1;34m\n\t<<< ${action} '${WB}${u}${locale}.ts' file >>>\n\033[m"
if [ "$u" == "" ]; then
eval $LUPDATE "$FILES" -ts "${WB}.ts" # locale-agnostic file
else
eval $LUPDATE "$FILES" -source-language en_US -target-language "${locale//-/_}" \
-ts "${WB}_${locale}.ts"
fi
}
normalize_crowdin_files() {
# Rename files which locales are different on FreeCAD and delete not supported locales
crowdin_fixes=(af-ZA ar-SA be-BY bg-BG ca-ES cs-CZ da-DK de-DE el-GR eu-ES fi-FI
fil-PH fr-FR gl-ES hr-HR hu-HU it-IT ja-JP ka-GE kab-KAB ko-KR lt-LT nl-NL
no-NO pl-PL ro-RO ru-RU sk-SK sl-SI sr-SP tr-TR uk-UA vi-VN)
crowdin_deletes=(az-AZ bn-BD br-FR bs-BA en en-GB en-US eo-UY es-CO es-VE et-EE fa-IR he-IL
hi-IN hy-AM id-ID kaa lv-LV mk-MK ms-MY sat-IN si-LK ta-IN te-IN th-TH ur-PK xav yo-NG)
for pattern in "${crowdin_fixes[@]}"; do
find . -type f -name "*_${pattern}\.*" | while read -r file; do
mv -v "$file" "${file//-*./.}"
done
done
for pattern in "${crowdin_deletes[@]}"; do
find . -type f -name "*_${pattern}\.*" -delete
done
}
help() {
echo -e "\nDescription:"
echo -e "\tCreate, update and release translation files."
echo -e "\nUsage:"
echo -e "\t./update_translation.sh [-R] [-U] [-r <locale>] [-u <locale>]"
echo -e "\nFlags:"
echo -e " -R\n\tRelease all translations (qm files)"
echo -e " -U\n\tUpdate all translations (ts files)"
echo -e " -r <locale>\n\tRelease the specified locale"
echo -e " -u <locale>\n\tUpdate strings for the specified locale"
echo -e " -N\n\tNormalize CrowdIn filenames"
}
# Main function ------------------------------------------------------------------------------------
LUPDATE=/usr/lib/qt6/bin/lupdate # from Qt6
# LUPDATE=lupdate # from Qt5
LRELEASE=/usr/lib/qt6/bin/lrelease # from Qt6
# LRELEASE=lrelease # from Qt5
WB="SearchBar"
sed -i '3s/-/_/' ${WB}*.ts # Enforce underscore on locales
sed -i '3s/\"en\"/\"en_US\"/g' ${WB}*.ts # Use en_US
if [ $# -eq 1 ]; then
if [ "$1" == "-R" ]; then
find . -type f -name '*_*.ts' | while IFS= read -r file; do
# Release all locales
$LRELEASE -nounfinished "$file"
echo
done
elif [ "$1" == "-U" ]; then
for locale in "${supported_locales[@]}"; do
update_locale "$locale"
done
elif [ "$1" == "-u" ]; then
update_locale # Update main file (agnostic)
elif [ "$1" == "-N" ]; then
normalize_crowdin_files
else
help
fi
elif [ $# -eq 2 ]; then
LOCALE="$2"
if is_locale_supported "$LOCALE"; then
if [ "$1" == "-r" ]; then
# Release locale (creation of *.qm file from *.ts file)
$LRELEASE -nounfinished "${WB}_${LOCALE}.ts"
elif [ "$1" == "-u" ]; then
# Update main & locale files
update_locale
update_locale "$LOCALE"
fi
else
echo "Verify your language code. Case sensitive."
echo "If it's correct, ask a maintainer to add support for your language on FreeCAD."
echo -e "\nSupported locales, '\033[1;34mFreeCADGui.supportedLocales()\033[m': \033[1;33m"
for locale in $(printf "%s\n" "${supported_locales[@]}" | sort); do
echo -n "$locale "
done
echo
fi
else
help
fi