嵌入式C程序资源化的思考
这里不考虑那些可以使用库的系统,比如可以使用 gettext 的 linux 系统,这里讨论的是一些很简单的系统,比如 ucos,以及很简单的界面库 ucgui。
一般的做法是将需要翻译的字符串汇集到一个数组中,然后使用函数来引用字符串,为了增加可读性,还会使用枚举。这里有篇文章讲解这种做法:Use Strings to Internationalize C Programs.
这种方法比较直接,优点是占用资源不高,很符合嵌入式的环境。缺点也明显:
- 手动量比较大。当然如果字符串少的话也没什么问题。添加一个新的字符串要在几处做更改,还需要保证数组的顺序。
- 不适合自动化生成。自动化并不能给你生成带有意义的枚举名,而且自动化脚本需要修改源文件,这会引发其他问题。
- 不直观,当维护时,源代码中的字符串看起来就没那么直观了,尤其是接手维护此代码的开发者。
因为用过 Qt ,对于它那种资源化/国际化方式特别喜欢,直观且优雅。后来了解了下 GNU gettext ,大体应该与 Qt 使用的方法类似。
自己也试着思考了下这些工具内部实现的原理。以 Qt 的 tr()
函数举例:
QString str = tr("C语言");
tr()
函数在运行时取出显示用的字符串,它使用的参数就是源代码中使用的字符串本身,这里就是"C语言"
,tr()
也应该是从一张表中查找翻译语言对应的字符串,没找到就返回它的参数。对于这个表查找应该使用了字符串hash 以提高查找效率。对于表的生成使用了外部工具对源代码进行处理,也就是自动化生成。
下面讲下我准备的思路:
-
源代码中需要翻译的字符串用一个宏封装,比如
_TR("some stting")
#define _TR(str) tr(str)
tr()
就是查找函数,用宏的好处在于灵活性。 - 字符串提取可以写个脚本,遍历所有的 C文件,逐行处理提取出所有的字符串,也可以顺带一些位置信息,比如提取自哪个文件哪一行。
-
tr()
函数查找的表是一个只读数组,数组元素类型定义大概如下:enum Language { LANG_DEFAULT, LANG_ZH_CN, LANG_EN, // ... LANG_LAST }; struct UniversalString { int hash; const char * const str[LANG_LAST]; };
结构定义
struct UniversalString
就是数组元素类型了,hash
的作用是为了加速字符串查找,使用良好的字符串hash函数的话,碰撞率很低,一个hash
域就足够了,否则可以添加多个存储使用不同 hash 函数产生的值。 -
表数组由脚本自动生成,自动产生字符串 hash 值,用原始字符串填充
str[LANG_DEFAULT]
,这样设计是因为字符串 hash 算法并不是 1对1,可以再进行一次字符串比较,这比直接在整个表中遍历逐个比较效率要高,而且还有个好处,对于翻译人员,有原始字符串更方便(这也可以通过添加注释实现)。如果想避免字符串比较,可以存储2个或多个不同 hash 函数的值,若这些值都相同,就认定字符串相同,这是个“概率保证”,如果 hash 函数足够好,这个认定失败的概率很低。一个示范表定义static const struct UniversalString strings[] = { {// ...\src\a.c:114 15, { "C语言", "", //... } }, {// ...\src\a.c:145 1563, { "some string", "", // ... } }, // ... };
-
函数
tr()
代码大概如下,其中find()
就是查找函数,get_lang()
返回的是当前的语言,返回值是枚举Language
中的取值。const char * tr(const char * str) { const struct UniversalString * ps = find(str); if(ps) { // found return ps.str[get_lang()]; } else { // not exist return str; } }
find()
函数就不写出了,这个函数优化的好,整体效率就不错。 -
如果是修改代码时候修改了字符串,重新生成时自动化工具应该可以保留一些未改动的字符串的已翻译内容,这是写工具要注意的事情。
参考资料:
3 年前
The primary social studies topic in primary school, environmental studies, or environmental education, is the most crucial one. Download the English, Hindi, and Urdu versions of the CBSE Class 1 EVS Model Paper 2023 in PDF format. CBSE Class 1 Evs Model Paper The EVS Sample Practice Questions Paper was recommended by the class teacher and topic specialists. For Class 1 exams held at the board and school levels, a chapter-wide solved question bank with the most crucial questions additionally recommended is provided with the CBSE Board EVS Model Paper 2023.
2 年前
This is an excellent post I seen thanks to share it. It is really what I wanted to see hope in future you will continue for sharing such a excellent post. เว็บหวย ไม่มี เลขอั้น จ่าย เต็ม
2 年前
I truly like you're composing style, incredible data, thankyou for posting. Nembutal in vendita
大约 1 年前
Thank you for very usefull information.. 먹튀검증
大约 1 年前
Its a great pleasure reading your post.Its full of information I am looking for and I love to post a comment that "The content of your post is awesome" Great work. 평택출장마사지
大约 1 年前
I admit, I have not been on this web page in a long time... however it was another joy to see It is such an important topic and ignored by so many, even professionals. I thank you to help making people more aware of possible issues. seriale turcesti
大约 1 年前
Really impressed! Everything is very open and very clear clarification of issues. It contains truly facts. Your website is very valuable. Thanks for sharing. Roofers in Rockwall
大约 1 年前
This particular papers fabulous, and My spouse and i enjoy each of the perform that you have placed into this. I’m sure that you will be making a really useful place. I has been additionally pleased. Good perform! เว็บแทงบอลดีที่สุดUFABET
大约 1 年前
You there, this is really good post here. Thanks for taking the time to post such valuable information. Quality content is what always gets the visitors coming. Fortune Tiger
大约 1 年前
Very interesting blog. Alot of blogs I see these days don't really provide anything that I'm interested in, but I'm most definately interested in this one. Just thought that I would post and let you know. Ac repair las vegas