关于中文化的核心,其实质是支持多语言的问题。由于对QT没有研究,但如果同realthunder所言,QT内部使用utf16编码来支持多语言编码问题,而当代操作系统默认配置使用utf8编码,那这个问题的解决,还是比较复杂,是需要通过编写一些函数,作为库函数,引入FreeCAD项目中来解决支持多种语言的问题。
从操作系统的视解来看,这是由于不同进程所需的运行环境,使用不同的字符编码方案,产生对于同一字节顺序流,在不同的字符编码转换表中查询时,得到不同的值,在将该值提交给GUI层后,被解释为不同的字符显示图样,而造成的结果。这与Linux发展早期(2000年左右)支持多语言的情况相同。如Linux终端中文输入环境cce
由于FreeCAD支持多操作系统平台,从长远考虑,而将来各类操作系统发行版,与字符编码相关的设置也可能会变化。QT也可能会使用不同的字符编码方案,来适应计算行业的发展变化。针对多语言支持问题,从长计议的话,建议在FreeCAD命令行程序列输出,与QT层之间,设计字符编码转换函数。同时,在QT与GUI函数之间,也设计相关函数来处理字符编码变化。
之前KiCAD也存在中文化(多语言化的)字符显示的问题,但6.0版本好象可以正常显示中文字符了。
如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
Moderator: paullee
Forum rules
论坛规矩 / 論壇規矩 , 有用的资讯 / 有用的資訊
论坛规矩 / 論壇規矩 , 有用的资讯 / 有用的資訊
-
- Posts: 126
- Joined: Wed Jul 03, 2019 8:15 am
-
- Veteran
- Posts: 2190
- Joined: Tue Jan 03, 2017 10:55 am
Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
其实FreeCAD现在基本上就是这样做的。编码处理很复杂,主要都是交由Qt来处理,QString的toUtf8的意思是从QString内部UTF16转换至UTF8通过QByteArray输出。QByteArray可以简单cast成C字符串。而fromUtf8则是将UTF8编码的QByteArray或者C字符串转换成UTF16存入QString。GUI,乃至与操作系统的交互,基本上都是通过Qt实现,所以不需要额外处理。felixlee868 wrote: ↑Sun Mar 06, 2022 12:13 am 由于FreeCAD支持多操作系统平台,从长远考虑,而将来各类操作系统发行版,与字符编码相关的设置也可能会变化。QT也可能会使用不同的字符编码方案,来适应计算行业的发展变化。针对多语言支持问题,从长计议的话,建议在FreeCAD命令行程序列输出,与QT层之间,设计字符编码转换函数。同时,在QT与GUI函数之间,也设计相关函数来处理字符编码变化。
Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
日期:2022/03/09
分支:realthunder-LinkDaily [https://github.com/realthunder/FreeCAD.git]
现在,我只需要在realthunder-LinkDaily分支上,修改一个代码位置,就能正常使用中文标识,十分感谢realthunder
修改位置:
FreeCADBase/Source Files/Tools.cpp文件
std::string Base::Tools::getIdentifier(const std::string& name)位置的下一行
直接return name;,使其不做处理,不当初限制窗口。
我在草绘界面,约束线段长度时,使用公式引用数据【Variables.测试属性】,线段长度正常变为10mm
使用Assembly4建立零件使用中文命名也正常,这对我已经够用了,十分感谢realthunder
现在感觉std::string Base::Tools::getIdentifier()这个函数挺微妙的... ...
前面所讲,我所指的中文命名的范围是指运行在python控制台的python代码函数括号内对象命名名称字符标识的部分,再加上属性部分。
=============================================================
以下是,未对std::string Base::Tools::getIdentifier()函数做出修改的表现
建立文档表现
>>> App.newDocument("未命名")
>>> # App.setActiveDocument("未�_�名")
>>> # App.ActiveDocument=App.getDocument("未�_�名")
>>> # Gui.ActiveDocument=Gui.getDocument("未�_�名")
建立零件出错,弹出错误弹窗
("(unicode error) 'utf-8' codec can't decode byte 0xe5 in position 3: invalid continuation byte", ('<string>', 1, 17, None))
添加属性正常,中文命名显示正常,但有时会出现限制弹窗,无法建立属性。
草绘无法建立矩形
10:22:29 Failed to add box: Unknown document '未�_�名'
10:22:29 App.getDocument('未�_�名').getObject('Sketch').addConstraint(Sketcher.Constraint('Coincident',-4,1,-1,1))
10:22:29 Unhandled exception in ViewProvider::eventCallback: Unknown document '未�_�名'
(Event type: SoMouseButtonEvent, object type: SketcherGui::ViewProviderSketch)
10:23:03 Failed to add box: Unknown document '未�_�名'
=============================================================
以下是,修改std::string Base::Tools::getIdentifier()函数,下一行直接return name;使函数不对字符做出任何处理,不会触发限制弹窗
①新建文档
>>> App.newDocument("未命名")
>>> # App.setActiveDocument("未命名")
>>> # App.ActiveDocument=App.getDocument("未命名")
>>> # Gui.ActiveDocument=Gui.getDocument("未命名")
②新建零件
>>> Gui.getDocument('未命名').ActiveView.setActiveObject('part', FreeCAD.getDocument('未命名').getObject('Part'), '')
>>> ### End command Std_Part
>>> Gui.runCommand('Asm4_newPart',0)
>>> # Gui.Selection.addSelection('未命名','测试_1')
选择浏览器的path显示为【未命名#测试_1】正常,到控制台也正常
>>> _obj, _matrix, _shp = App.getDocument('未命名').getObject('测试_1').getSubObject('', retType=2)
>>>
③建立属性
零件对象的属性页面,建立组名【结构体】属性名【属性测试_1】属性,显示正常,删除属性正常,再建立正常
零件建立Variables面板正常,Variables面板对象的属性界面,添加属性正常,选择浏览器正常
>>> # Gui.Selection.clearSelection()
>>> # Gui.Selection.addSelection('未命名','测试_1','Variables.')
物品路径path显示【未命名#测试_1.Variables.】,
选择流量器,到python控制台正常
>>> _obj, _matrix, _shp = App.getDocument('未命名').getObject('测试_1').getSubObject('Variables.', retType=2)
④公式引用属性正常
在草绘视图里约束线段长度正常,在公式界面输入前面建立的Variables面板,再输入.选择中文命名的属性正常,约束自动改变正常
>>> App.getDocument('未命名').getObject('Sketch').addConstraint(conList)
>>>
>>> App.getDocument('未命名').getObject('Sketch').addConstraint(Sketcher.Constraint('PointOnObject',0,1,-1))
>>> # Gui.Selection.addSelection('未命名','Sketch','Edge1',36.4273,0,0.008,False)
>>> ### Begin command Sketcher_ConstrainDistanceX
>>> App.getDocument('未命名').getObject('Sketch').addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,85.814376))
>>> ### End command Sketcher_ConstrainDistanceX
>>> # Gui.Selection.clearSelection()
⑤改变属性正常值正常,草绘界面也正常变化。
>>> # Gui.Selection.addSelection('未命名','Sketch')
>>> # Gui.Selection.clearSelection()
>>> # Gui.Selection.addSelection('未命名','测试_1','Variables.')
>>> FreeCAD.getDocument('未命名').getObject('Variables').属性测试_4 = 3.0000
>>>
>>> FreeCAD.getDocument('未命名').getObject('Variables').属性测试_4 = 30.0000
>>>
>>> # Gui.Selection.clearSelection()
⑥存储再读取,显示也正常
>>> # Gui.Selection.clearSelection()
>>> ### Begin command Std_SaveAs
>>> Gui.SendMsgToActiveView("SaveAs")
>>> App.getDocument("未命名").saveAs(u"C:/Users/wdy/Documents/\u5b58\u50a8\u6d4b\u8bd5_1.FCStd")
>>> ### End command Std_SaveAs
>>> ### Begin command Std_Open
>>> FreeCADGui.reload('未命名')
>>> ### End command Std_Open
>>> App.closeDocument("未命名")
>>> # App.setActiveDocument("")
>>> # App.ActiveDocument=None
>>> # Gui.ActiveDocument=None
>>> ### Begin command Std_Open
>>> FreeCAD.openDocument('C:/Users/wdy/Documents/\u5b58\u50a8\u6d4b\u8bd5_1.FCStd')
>>> # App.setActiveDocument("存储测试_1")
>>> # App.ActiveDocument=App.getDocument("存储测试_1")
>>> # Gui.ActiveDocument=Gui.getDocument("存储测试_1")
>>> ### End command Std_Open
>>> # Gui.Selection.addSelection('存储测试_1','Sketch')
>>> _obj, _matrix, _shp = App.getDocument('存储测试_1').getObject('Sketch').getSubObject('', retType=2)
>>>
十分感谢realthunder
看着python控制台执行的一行一行代码,不是一堆下滑线,终于感觉使用不在难受。
我所指的中文命名的范围是指函数括号内对象命名名称字符标识的部分,再加上属性部分。(属性仅是值的标识,不是函数)
>>> FreeCAD.getDocument('未命名').getObject('Variables').属性测试_4
虽然在python中函数也可以用中文标识,但这仅是我个人编程习惯,这个还是遵循FreeCAD的编程规范为好。
FreeCAD控制台运行的python代码的函数括号内的字符对象能支持中文标识,我是觉得这更加符合人们的使用直觉。
分支:realthunder-LinkDaily [https://github.com/realthunder/FreeCAD.git]
现在,我只需要在realthunder-LinkDaily分支上,修改一个代码位置,就能正常使用中文标识,十分感谢realthunder
修改位置:
FreeCADBase/Source Files/Tools.cpp文件
std::string Base::Tools::getIdentifier(const std::string& name)位置的下一行
直接return name;,使其不做处理,不当初限制窗口。
我在草绘界面,约束线段长度时,使用公式引用数据【Variables.测试属性】,线段长度正常变为10mm
使用Assembly4建立零件使用中文命名也正常,这对我已经够用了,十分感谢realthunder
现在感觉std::string Base::Tools::getIdentifier()这个函数挺微妙的... ...
前面所讲,我所指的中文命名的范围是指运行在python控制台的python代码函数括号内对象命名名称字符标识的部分,再加上属性部分。
=============================================================
以下是,未对std::string Base::Tools::getIdentifier()函数做出修改的表现
建立文档表现
>>> App.newDocument("未命名")
>>> # App.setActiveDocument("未�_�名")
>>> # App.ActiveDocument=App.getDocument("未�_�名")
>>> # Gui.ActiveDocument=Gui.getDocument("未�_�名")
建立零件出错,弹出错误弹窗
("(unicode error) 'utf-8' codec can't decode byte 0xe5 in position 3: invalid continuation byte", ('<string>', 1, 17, None))
添加属性正常,中文命名显示正常,但有时会出现限制弹窗,无法建立属性。
草绘无法建立矩形
10:22:29 Failed to add box: Unknown document '未�_�名'
10:22:29 App.getDocument('未�_�名').getObject('Sketch').addConstraint(Sketcher.Constraint('Coincident',-4,1,-1,1))
10:22:29 Unhandled exception in ViewProvider::eventCallback: Unknown document '未�_�名'
(Event type: SoMouseButtonEvent, object type: SketcherGui::ViewProviderSketch)
10:23:03 Failed to add box: Unknown document '未�_�名'
=============================================================
以下是,修改std::string Base::Tools::getIdentifier()函数,下一行直接return name;使函数不对字符做出任何处理,不会触发限制弹窗
①新建文档
>>> App.newDocument("未命名")
>>> # App.setActiveDocument("未命名")
>>> # App.ActiveDocument=App.getDocument("未命名")
>>> # Gui.ActiveDocument=Gui.getDocument("未命名")
②新建零件
>>> Gui.getDocument('未命名').ActiveView.setActiveObject('part', FreeCAD.getDocument('未命名').getObject('Part'), '')
>>> ### End command Std_Part
>>> Gui.runCommand('Asm4_newPart',0)
>>> # Gui.Selection.addSelection('未命名','测试_1')
选择浏览器的path显示为【未命名#测试_1】正常,到控制台也正常
>>> _obj, _matrix, _shp = App.getDocument('未命名').getObject('测试_1').getSubObject('', retType=2)
>>>
③建立属性
零件对象的属性页面,建立组名【结构体】属性名【属性测试_1】属性,显示正常,删除属性正常,再建立正常
零件建立Variables面板正常,Variables面板对象的属性界面,添加属性正常,选择浏览器正常
>>> # Gui.Selection.clearSelection()
>>> # Gui.Selection.addSelection('未命名','测试_1','Variables.')
物品路径path显示【未命名#测试_1.Variables.】,
选择流量器,到python控制台正常
>>> _obj, _matrix, _shp = App.getDocument('未命名').getObject('测试_1').getSubObject('Variables.', retType=2)
④公式引用属性正常
在草绘视图里约束线段长度正常,在公式界面输入前面建立的Variables面板,再输入.选择中文命名的属性正常,约束自动改变正常
>>> App.getDocument('未命名').getObject('Sketch').addConstraint(conList)
>>>
>>> App.getDocument('未命名').getObject('Sketch').addConstraint(Sketcher.Constraint('PointOnObject',0,1,-1))
>>> # Gui.Selection.addSelection('未命名','Sketch','Edge1',36.4273,0,0.008,False)
>>> ### Begin command Sketcher_ConstrainDistanceX
>>> App.getDocument('未命名').getObject('Sketch').addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,85.814376))
>>> ### End command Sketcher_ConstrainDistanceX
>>> # Gui.Selection.clearSelection()
⑤改变属性正常值正常,草绘界面也正常变化。
>>> # Gui.Selection.addSelection('未命名','Sketch')
>>> # Gui.Selection.clearSelection()
>>> # Gui.Selection.addSelection('未命名','测试_1','Variables.')
>>> FreeCAD.getDocument('未命名').getObject('Variables').属性测试_4 = 3.0000
>>>
>>> FreeCAD.getDocument('未命名').getObject('Variables').属性测试_4 = 30.0000
>>>
>>> # Gui.Selection.clearSelection()
⑥存储再读取,显示也正常
>>> # Gui.Selection.clearSelection()
>>> ### Begin command Std_SaveAs
>>> Gui.SendMsgToActiveView("SaveAs")
>>> App.getDocument("未命名").saveAs(u"C:/Users/wdy/Documents/\u5b58\u50a8\u6d4b\u8bd5_1.FCStd")
>>> ### End command Std_SaveAs
>>> ### Begin command Std_Open
>>> FreeCADGui.reload('未命名')
>>> ### End command Std_Open
>>> App.closeDocument("未命名")
>>> # App.setActiveDocument("")
>>> # App.ActiveDocument=None
>>> # Gui.ActiveDocument=None
>>> ### Begin command Std_Open
>>> FreeCAD.openDocument('C:/Users/wdy/Documents/\u5b58\u50a8\u6d4b\u8bd5_1.FCStd')
>>> # App.setActiveDocument("存储测试_1")
>>> # App.ActiveDocument=App.getDocument("存储测试_1")
>>> # Gui.ActiveDocument=Gui.getDocument("存储测试_1")
>>> ### End command Std_Open
>>> # Gui.Selection.addSelection('存储测试_1','Sketch')
>>> _obj, _matrix, _shp = App.getDocument('存储测试_1').getObject('Sketch').getSubObject('', retType=2)
>>>
十分感谢realthunder
看着python控制台执行的一行一行代码,不是一堆下滑线,终于感觉使用不在难受。
我所指的中文命名的范围是指函数括号内对象命名名称字符标识的部分,再加上属性部分。(属性仅是值的标识,不是函数)
>>> FreeCAD.getDocument('未命名').getObject('Variables').属性测试_4
虽然在python中函数也可以用中文标识,但这仅是我个人编程习惯,这个还是遵循FreeCAD的编程规范为好。
FreeCAD控制台运行的python代码的函数括号内的字符对象能支持中文标识,我是觉得这更加符合人们的使用直觉。
Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
还有一些其他的中文输入问题
在window平台上,输出的文件,有中文的路径,就会输出失败。
OS: Windows 10 Version 2009
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.24267 +99 (Git)
Build type: Release
Branch: Branch_0.19.3
Hash: 6530e364184ce05ccff39501e175cf2237e6ee4b
Python version: 3.8.6+
Qt version: 5.15.2
Coin version: 4.0.1
OCC version: 7.5.3
Locale: Chinese/China (zh_CN)
在window平台上,输出的文件,有中文的路径,就会输出失败。
OS: Windows 10 Version 2009
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.24267 +99 (Git)
Build type: Release
Branch: Branch_0.19.3
Hash: 6530e364184ce05ccff39501e175cf2237e6ee4b
Python version: 3.8.6+
Qt version: 5.15.2
Coin version: 4.0.1
OCC version: 7.5.3
Locale: Chinese/China (zh_CN)
-
- Veteran
- Posts: 2190
- Joined: Tue Jan 03, 2017 10:55 am
Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
这个还是需要限制下的,因为getIdentifier()在其他地方还会被用到,比如对象或者属性名称,如果不符合Python标识命名规范就可能在运行Python代码时出错.我查了下,你遇到的这个错误是因为我在getIdentifier里使用了boost::regex,而boost::regex在Windows下默认编码处理与其它操作系统不同(参看这里).Unicode方式下Windows程序使用的字符串是wchar_t.boost::regex可能在Windows下是默认转码至wchar_t,也就是UTF-16然后处理.对于普通char字符串通过区域设置决定编码,而这个编码在Windows区域设置中似乎没有UTF8的选项,导致转码后出现乱码.如果编译boost::regex库时定义了BOOST_REGEX_NO_W32,则不会转码至UTF16,测试结果就正常,虽然也会有些问题,比如无法识别全角空格,但是Python标识不允许全角空格.另外,很多情况下编译FreeCAD只是把boost作为第三方库使用,没法控制编译时究竟有没有定义BOOST_REGEX_NO_W32,所以最好还是干脆不用.
我之后又试过Qt的QRegularExpression,可以用.但是后来还是决定直接使用Python的标识符判断函数.这样可以保证得到的是合法标识.另外我也改了下Spreadsheet alias命名,同样使用getIdentifier()来做判断.
-
- Veteran
- Posts: 2190
- Joined: Tue Jan 03, 2017 10:55 am
Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
能发下具体的错误信息吗.我试了下,似乎只是'开始'页面会报错.你可以下载我改过的代码,直接复制到FreeCAD安装目录中Mod/Start/StartPage子目录里.注意备份原始文件StartPage.pymuzilier wrote: ↑Fri Mar 11, 2022 2:51 am 还有一些其他的中文输入问题
在window平台上,输出的文件,有中文的路径,就会输出失败。
OS: Windows 10 Version 2009
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.24267 +99 (Git)
Build type: Release
Branch: Branch_0.19.3
Hash: 6530e364184ce05ccff39501e175cf2237e6ee4b
Python version: 3.8.6+
Qt version: 5.15.2
Coin version: 4.0.1
OCC version: 7.5.3
Locale: Chinese/China (zh_CN)
-
- Posts: 126
- Joined: Wed Jul 03, 2019 8:15 am
Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里
如果动手解决国际化问题,建议从宏观角度考虑清楚后,来真正解决这个问题。
从本人学习FreeCAD近五年的经历来看,FreeCAD所依赖的QT层,操作系统GUI层,Python都在不停向前演进变化着。以MacOS为例,由于其将移动界面与桌面打通的开发战略的实施,MacOS的GUI层的架构完全改变。这造成QT的版本升级遇到问题。有一段时间由于QT没有修正相关问题,造成FreeCAD无法启动GUI界面。
我相信其它如Linux的不同发行版本以及Windows的一些发行版本也会出现一些问题。
现在来分析FreeCAD系统的架构。由于FreeCAD命令行解释器,通过Python与QT层进行交互。由于Python可能使用utf-8字符编码,而QT使用utf-16编码,这会造成在QT与Python之间,汉字图样显示不正常。这只是中文语言环境中的一个问题。如果在其它语言环境中,还有左右读写顺序等问题。
另外,与FreeCAD相伴的其它许多第三方科学计算工具,如ccx,gmsh等的开发,完成与FreeCAD项目无关,根本不可能要求其它项目也按utf-8或utf-16等编码来进行软件开发。(由于文化背景不同,开发人员对项目解决技术问题的侧重点不一等原因)。因此为增加FreeCAD项目的灵活性,首先在FreeCAD项目中,标准化不同字符编码,在Python->QT->GUI层之间的转换,是解决问题的第一步。
如果在FreeCAD项目所依赖的不同层之间,通过参数来实现不同字符编码之间的转换,就可以为其它问题的解决,提供一个坚实的基础。
从本人学习FreeCAD近五年的经历来看,FreeCAD所依赖的QT层,操作系统GUI层,Python都在不停向前演进变化着。以MacOS为例,由于其将移动界面与桌面打通的开发战略的实施,MacOS的GUI层的架构完全改变。这造成QT的版本升级遇到问题。有一段时间由于QT没有修正相关问题,造成FreeCAD无法启动GUI界面。
我相信其它如Linux的不同发行版本以及Windows的一些发行版本也会出现一些问题。
现在来分析FreeCAD系统的架构。由于FreeCAD命令行解释器,通过Python与QT层进行交互。由于Python可能使用utf-8字符编码,而QT使用utf-16编码,这会造成在QT与Python之间,汉字图样显示不正常。这只是中文语言环境中的一个问题。如果在其它语言环境中,还有左右读写顺序等问题。
另外,与FreeCAD相伴的其它许多第三方科学计算工具,如ccx,gmsh等的开发,完成与FreeCAD项目无关,根本不可能要求其它项目也按utf-8或utf-16等编码来进行软件开发。(由于文化背景不同,开发人员对项目解决技术问题的侧重点不一等原因)。因此为增加FreeCAD项目的灵活性,首先在FreeCAD项目中,标准化不同字符编码,在Python->QT->GUI层之间的转换,是解决问题的第一步。
如果在FreeCAD项目所依赖的不同层之间,通过参数来实现不同字符编码之间的转换,就可以为其它问题的解决,提供一个坚实的基础。