En las siguientes notas, "context" debe ser el nombre de su complemento o entorno de trabajo, por ejemplo, "MySuperAddon" o "DraftPlus", o cualquier otro. Aquí importa el uso de mayúsculas: "Context" no es lo mismo que "context", por ejemplo. El contexto permite que todas las traducciones de su código se agrupen bajo el mismo nombre, para que los traductores puedan identificarlas más fácilmente. Es decir, sabrán exactamente a qué complemento o entorno de trabajo pertenece una cadena de texto en particular.
Nota: Aquí tiene un script todo en uno que automatiza el procedimiento completo mencionado a continuación (aunque se recomienda leer el procedimiento para saber qué debe hacer el script): https://github.com/yorikvanhavre/BIM_Workbench/blob/master/utils/updateTranslations.py
translations/. Puedee cambiarle el nombre, pero este será más sencillo, ya que es el mismo en todo FreeCAD. En esta carpeta, colocará los archivos .ts (los archivos de traducción "fuente") y los archivos .qm (los archivos de traducción compilados).FreeCAD.Console se muestra en la "Vista de informe" y, por lo tanto, debe traducirse. La "Vista de informe" es diferente de la consola de Python.
translate(). Debe llamarse exactamente translate: el extractor de cadenas se basa en ese nombre exacto. Puede usar el nombre completo de Qt, pero es un poco más limpio usar:import FreeCAD
translate = FreeCAD.Qt.translate
translate():print("My text")
print(translate("context", "My text"))
Tenga en cuenta que translate() no es una función normal: también sirve como "etiqueta" para la utilidad de procesamiento de texto lupdate, por lo que debe llamarse exactamente "translate". El programa lupdate es un procesador de texto simple; no ejecuta su código. Debe pasar cadenas literales directamente a la función translate(): no puede pasar variables, constantes, etc. Por ejemplo:
# This works:
FreeCAD.Console.PrintMessage(translate("context", "My text") + "\n")
# This does not, lupdate only sees the word "a_variable", and doesn't know what that is:
a_variable = "My text"
FreeCAD.Console.PrintMessage(translate("context", a_variable ) + "\n")
# But this works -- a_variable will contain the translated string:
a_variable = translate("context", "My text")
FreeCAD.Console.PrintMessage(a_variable + "\n")
Esto se puede usar en cualquier lugar: en print(), en FreeCAD.Console.PrintMessage(), en diálogos de Qt, etc. Las funciones FreeCAD.Console no agregan automáticamente el carácter de nueva línea (\n), por lo que, si se desea, se debe agregar al final. Este carácter tampoco necesita traducción, por lo que puede estar fuera de la función de traducción:
FreeCAD.Console.PrintMessage(translate("context", "My text") + "\n")
.ui creados con QtDesigner, no es necesario realizar ninguna acción especial.QT_TRANSLATE_NOOP:obj.addProperty("App::PropertyBool", "MyProperty", "PropertyGroup", QT_TRANSLATE_NOOP("App::Property", "This is what My Property does"))
"context" en este caso específico. Mantenga "App::Property".
from PySide.QtCore import QT_TRANSLATE_NOOP
La función QT_TRANSLATE_NOOP no hace nada, pero marca los textos que la utilidad lupdate procesará posteriormente. Solo la utilizamos en casos especiales donde FreeCAD se encarga de todo.
"Workbench" como contexto:self.appendMenu(QT_TRANSLATE_NOOP("Workbench", "My menu"), [list of commands, ...])
self.appendToolbar(QT_TRANSLATE_NOOP("Workbench", "My toolbar"), [list of commands, ...])
translations/ y actualice la configuración regional en la función Initialized:FreeCADGui.addLanguagePath("/path/to/translations")
FreeCADGui.updateLocale()
El archivo InitGui.py no tiene el atributo 'file, por lo que no es fácil encontrar la ubicación relativa de la carpeta de traducciones. Una forma sencilla de solucionar esto es hacer que importe otro archivo de la misma carpeta y, en ese archivo, hacer lo siguiente:
FreeCADGui.addLanguagePath(os.path.join(os.path.dirname(__file__), "translations"))
FreeCADGui.updateLocale()
def QT_TRANSLATE_NOOP(context, text):
return text
'MenuText' y el 'Tooltip' del comando de esta manera:def GetResources(self):
return {'Pixmap' : "path/to/icon.svg"),
'MenuText': QT_TRANSLATE_NOOP("CommandName", "My Command"),
'ToolTip' : QT_TRANSLATE_NOOP("CommandName", "Describes what the command does"),
'Accel' : "Shift+A"
}
"CommandName" es el nombre del comando, definido por:FreeCADGui.addCommand('CommandName', My_Command_Class())
lupdate, lconvert, lrelease y pylupdate. En las distribuciones de Linux, suelen venir en paquetes llamados pyside-tools o pyside2-tools. En algunos sistemas, lupdate se llama lupdate4, lupdate5, lupdate-qt4 o similar. Lo mismo ocurre con las demás herramientas. Puede usar la versión Qt4 o Qt5 según su preferencia. En Qt6 no existe un sistema de traducción independiente para archivos Python; lupdate se utiliza para extraer cadenas de todo tipo de archivos fuente..ui, primero debe ejecutar lupdate:lupdate *.ui -ts translations/uifiles.ts
.ui dentro de toda su estructura de directorios..py, también necesita ejecutar pylupdate:pylupdate *.py -ts translations/pyfiles.ts
lconvert -i translations/uifiles.ts translations/pyfiles.ts -o translations/MyModule.ts
.ts para asegurarse de que contienen las cadenas; luego puede eliminar tanto pyfiles.ts como uifiles.ts.#!/bin/sh
lupdate *.ui -ts translations/uifiles.ts
pylupdate *.py -ts translations/pyfiles.ts
lconvert -i translations/uifiles.ts translations/pyfiles.ts -o translations/MyModule.ts
rm translations/pyfiles.ts
rm translations/uifiles.ts
Es momento de traducir su archivo .ts. Puede crear una cuenta en una plataforma de traducción pública como Crowdin o Transifex, o puede aprovechar nuestra cuenta existente FreeCAD-addons en Crowdin, que ya cuenta con muchos usuarios, lo que aumenta las posibilidades de que su archivo sea traducido rápidamente por personas que conocen FreeCAD.
Si desea alojar su archivo en la cuenta FreeCAD Crowdin, póngase en contacto con Yorik en el FreeCAD forum.
Nota: Algunas plataformas como Crowdin pueden integrarse con GitHub y realizar automáticamente todo el proceso de los puntos 2, 3 y 4. Para que esto sea posible, no podrá usar la cuenta de FreeCAD Crowdin; tendrá que crear su propia cuenta.
Una vez que su archivo .ts haya sido traducido, aunque sea parcialmente, puede descargar las traducciones desde el sitio:
.zip que contiene un archivo .ts por idioma..ts traducidos, junto con tu archivo .ts base, en la carpeta translations/.
Ahora ejecute el programa lrelease en cada archivo que tenga:
lrelease "translations/Draft_de.ts"
lrelease "translations/Draft_fr.ts"
lrelease "translations/Draft_pt-BR.ts"
Puede automatizar el proceso:
for f in translations/*_*.ts
do
lrelease "translations/$f"
done
Debería encontrar un archivo .qm por cada archivo .ts traducido. Los archivos .qm son los que usarán Qt y FreeCAD durante la ejecución.
Eso es todo lo que necesita. Tenga en cuenta que algunas partes de su entorno de trabajo no se pueden traducir automáticamente si cambia de idioma. En ese caso, tendrá que reiniciar FreeCAD para que el nuevo idioma surta efecto.
FreeCADGui.addTranslationPath("/ruta/a/la/carpeta/que/contiene/el/archivo/qm")FreeCAD.Qt.translate("tu contexto","alguna cadena")Resultado: Esto debería proporcionarle la traducción al alemán. Si funciona, la configuración básica es correcta. Entonces podemos analizar otros aspectos. Por ejemplo, los nombres de los comandos siempre deben usar un contexto especial, que es el nombre del comando tal como está registrado en FreeCAD.
Yorik mantiene un script práctico para el entorno de trabajo BIM que permite recopilar, cargar y descargar archivos .ts.
Simplemente copie y adapte ese script para su entorno de trabajo:
https://github.com/yorikvanhavre/BIM_Workbench/blob/master/utils/updateTranslations.py
En los ejemplos anteriores se utilizan dos funciones distintas: translate() y QT_TRANSLATE_NOOP. También es posible encontrar tr() y QT_TR_NOOP, que proporcionan automáticamente el argumento "context" según su ubicación de llamada. Estos dos pares de funciones son fundamentalmente diferentes.
Las funciones translate() y tr() realizan dos tareas distintas: en tiempo de ejecución, llevan a cabo la traducción real de la cadena que se les pasa a la cadena traducida final. Esto se cumple tanto si se les proporciona una cadena literal, una variable o una constante: la búsqueda es dinámica y en tiempo real durante la ejecución del código. Sin embargo, proporcionan una función adicional fuera del tiempo de ejecución: son reconocidas por la utilidad pylupdate. Si (y solo si) contienen una cadena literal, esta se extrae mediante la utilidad. SOLO las cadenas literales son extraídas por pylupdate; si se pasa una variable, esta se ignora. Qt intentará proporcionar una traducción en tiempo de ejecución, pero esto solo funcionará si otra parte del código llama a una de las funciones de traducción con la cadena literal que necesita ser traducida, de modo que pylupdate pueda extraerla. Tenga en cuenta que el código con la cadena literal no necesita ejecutarse nunca, simplemente debe existir como una línea de código en algún archivo: pylupdate no realiza ningún análisis ni ejecución de código, simplemente realiza una búsqueda y extracción de cadena.
En cambio, QT_TRANSLATE_NOOP y QT_TR_NOOP no hacen absolutamente nada en tiempo de ejecución: son literalmente "no-ops" y el código en ejecución las ignora por completo. Su único uso es marcar una cadena literal para su extracción por pylupdate: nunca tiene sentido colocar una variable dentro de una llamada a una de estas funciones, ya que no tendrá ningún efecto. Se utilizan en circunstancias en las que se llamará a translate() o tr() con una variable que contiene el texto a traducir. Por ejemplo, cualquier código que se utilice para crear un Comando o una Propiedad utilizará una función de tipo NOOP alrededor del texto del menú del comando o la información sobre herramientas, o la cadena de documentación de la propiedad: en tiempo de ejecución, cuando FreeCAD muestra estos elementos al usuario, llama a translate(): las cadenas literales deben haber sido extraídas por pylupdate en el punto de creación, por ejemplo:
def GetResources(self):
return {'Pixmap' : "path/to/icon.svg",
'MenuText': QT_TRANSLATE_NOOP("CommandName", "My Command"),
'ToolTip' : QT_TRANSLATE_NOOP("CommandName", "Describes what the command does"),
'Accel' : "Shift+A"
}
En este uso, en tiempo de ejecución el diccionario devuelto por esta función es literalmente:
{
'Pixmap' : "path/to/icon.svg",
'MenuText': "My Command",
'ToolTip' : "Describes what the command does",
'Accel' : "Shift+A"
}
No hay ninguna referencia a ningún tipo de información de traducción. Cuando FreeCAD muestra esta información al usuario, el pseudocódigo es:
for command in commands:
resources = command.GetResources()
menu_text = translate(resources['MenuText'])
En este caso, lupdate no puede extraer ninguna cadena de la llamada a translate() porque hace referencia a una variable. Por lo tanto, lupdate ignora esa llamada, pero en tiempo de ejecución Qt busca la cadena que se le pasa. Siempre que en algún lugar del código haya una llamada a una de las funciones de traducción con una cadena literal coincidente (en este caso, en la función GetResources()), esta llamada de traducción se realizará correctamente.
Para verificar que se están extrayendo las cadenas esperadas, puede ejecutar manualmente el comando pylupdate:
pylupdate myfile.py -ts outfile.ts
El archivo outfile.ts contendrá el conjunto de cadenas que se cargan en CrowdIn para su traducción.
openCommand() (hilo del foro)