当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]嵌入式系统多语言文本解决方案

嵌入式系统开发中,某些产品可能会需要跨区域销售,因此,通常会有多语言的需求。对于这一类多语言需求的解决,在嵌入式产品中有其特殊的地方。以下,给出一种可能的解决方案。

该方案的核心思想是为所有文本建立索引,通过索引可以得到特定语言的文字编码,随后通过该编码获得字库资源,并进行输出。在这过程中,唯一需要注意的是对于特殊的某些语言,如阿拉伯语等的处理。(阿拉伯语字符在连写时,其形状会发生变化。)

1. 字库的建立:

文本最终都将输出给用户,因此,必须为文本内容指定字库。本方案中采用UNICODE编码字库。字库文件采用二进制存储,按UNICODE编码顺序排列存储点阵数据,点阵大小为24*24。

2. 文本资源文件:

文本资源文件描述了特定语言的文本内容,以及相关的字符编码。例如对于Chinese.cfg文件来说,就保留了一个索引为1的文本,该文本内容为“确认”;相应对于English.cfg文件来说,必然会同样有一个索引为1的文本,该文本内容为“CONfirm”。通过对所有的文本建立索引并生成文本资源文件,就为最终的解决扫清了障碍。

文本资源文件采用二进制存储。文件头部16个字节为描述性信息,之后是文本映射表,紧跟映射表之后为文本的实际Unicode编码。

3. 对文本资源文件进行描述的数据结构

  typedef STruct _txtres_fileheader {

  LONG lFileType; //文件类型,0x2E434647=‘.CFG‘

  LONG lVersionNum; //适用版本,0x56313032=‘V102‘

  LONG lMapOffset; //偏移量,文件头到文本映射区的偏移量

  LONG lDataOffset; //偏移量,文件头到文本数据区的偏移量

  } APPteXT_FILEHEADER;

4. 文本映射表结构

  typedef struct _txtres_txtmap {

  WORD wTextIndes; //当前文本的索引值

  WORD wTextSize; //当前文本的Unicode编码所占用的字节数

  LONG lUnicodeOffset; //从文件头到当前文本Unicode编码存储位置的偏移量

  } TXTRES_TXTMAP;

5. 特殊语言(阿拉伯语等)的解决

特殊语言在连写时可能发生变化,因此采用固定字库可能无法解决该问题。针对这种状况可以直接新增一个自定义字库。以阿拉伯语为例,该字库的处理过程如下:

a. 首先将阿拉伯的文本内容按预定格式(例如24*24)在windows系统上显示输出,并将内容保存为图片格式。此时图片中便为连写内容。

b. 随后,对图片进行分割。如按照24*24进行分割便可得到特定的24*24大小的字库内容。

c. 最后,将原先的UNICODE编码转为按照之前生成的字库来编码。

d. 之后在程序代码中就可利用自定义字库与自定义编码来显示阿拉伯语。

最后附上部分示例代码。

  //定义文本配置文件路径

  #define TXT_FILE_ENGLISH "config/English.cfg"

  #define TXT_FILE_CHINASIM "config/ChinaSim.cfg"

  #define TXT_FILE_CHINATRA "config/ChinaTra.cfg"

  #define TXT_FILE_KOREAN "config/Korean.cfg"

  #define TXT_FILE_JAPANESE "config/Japanese.cfg"

  #define TXT_FILE_SPANISH "config/Spanish.cfg"

  #define TXT_FILE_RUSSIAN "config/Russian.cfg"

  #define TXT_FILE_THAI "config/Thai.cfg"

  #define TXT_FILE_GERMAN "config/German.cfg"

  #define TXT_FILE_FRANCE "config/France.cfg"

  #define TXT_FILE_ITALY "config/Italy.cfg"

  #define TXT_FILE_ARABIA "config/Arabia.cfg"

  #define TXT_FILE_PORTUGAL "config/Portugal.cfg"

  #define TXT_FILE_HINDI "config/Hindi.cfg"

  #define TXT_FILE_TURKISH "config/Turkish.cfg"[!--empirenews.page--]

  #define TXT_FILE_VIETNAM "config/Vietnam.cfg"

  #define TXT_FILE_SWIDISH "config/Swedish.cfg"

  #define TXT_FILE_POLISH "config/Polish.cfg"

  //根据文本索引及文本语言,读取相应的文本配置文件,以得到该文本,成功返回有效指针

  GUISTRING * GetTextResource(LONG lIndex, LONG lLanguage)

  {

  GUISTRING * pTxt;

  APPTEXT_FILEHEADER fh;

  APPTEXT_MAPPING map;

  STRING strFile;

  WORD * pBuf;

  int fd, iOff;

  //确定要读取的配置文件

  switch (lLanguage)

  {

  case TXT_LANG_ENGLISH:

  strFile = TXT_FILE_ENGLISH;

  break;

  case TXT_LANG_CHINASIM:

  strFile = TXT_FILE_CHINASIM;

  break;

  case TXT_LANG_CHINATRA:

  strFile = TXT_FILE_CHINATRA;

  break;

  case TXT_LANG_KOREAN:

  strFile = TXT_FILE_KOREAN;

  break;

  case TXT_LANG_JAPANESE:

  strFile = TXT_FILE_JAPANESE;

  break;

  case TXT_LANG_SPANISH:

  strFile = TXT_FILE_SPANISH;

  break;

  case TXT_LANG_RUSSIAN:

  strFile = TXT_FILE_RUSSIAN;

  break;

  case TXT_LANG_THAI:

  strFile = TXT_FILE_THAI;

  break;

  case TXT_LANG_GERMAN:

  strFile = TXT_FILE_GERMAN;

  break;

  case TXT_LANG_FRANCE:

  strFile = TXT_FILE_FRANCE;

  break;

  case TXT_LANG_ITALY:

  strFile = TXT_FILE_ITALY;

  break;

  case TXT_LANG_ARABIA:

  strFile = TXT_FILE_ARABIA;

  break;

  case TXT_LANG_PORTUGAL:

  strFile = TXT_FILE_PORTUGAL;

  break;

  case TXT_LANG_HINDI:

  strFile = TXT_FILE_HINDI;

  break;

  case TXT_LANG_TURKISH:

  strFile = TXT_FILE_TURKISH;

  break;

  case TXT_LANG_VIETNAM:

  strFile = TXT_FILE_VIETNAM;

  break;

  case TXT_LANG_SWIDISH:

  strFile = TXT_FILE_SWIDISH;

  break;

  case TXT_LANG_POLISH:[!--empirenews.page--]

  strFile = TXT_FILE_POLISH;

  break;

  default:

  return NULL;

  }

  //打开配置文件并检查其格式

  if ((fd = open(strFile, O_RDONLY)) == -1)

  {

  return NULL;

  }

  if (read(fd, &fh, 16) != 16)

  {

  close(fd);

  return NULL;

  }

  if (fh.lFileType != 0x4746432E || fh.lVersionNum != 0x32303156)

  {

  close(fd);

  return NULL;

  }

  //在文本映射区内查找匹配的文本索引

  for (iOff = fh.lMapOffset; iOff < fh.lDataOffset; iOff += 8)

  {

  if (read(fd, &map, 8) != 8)

  {

  close(fd);

  return NULL;

  }

  if (map.wTextIndex == lIndex)

  {

  break;

  }

  }

  if (iOff >= fh.lDataOffset)

  {

  close(fd);

  return NULL;

  }

  //根据找到的文本映射来读取文本内容

  if (!(pBuf = GuiMemAlloc(map.wTextSize + 2)))

  {

  close(fd);

  return NULL;

  }

  lseek(fd, fh.lDataOffset + map.lTextOffset, SEEK_SET);

  if (read(fd, pBuf, map.wTextSize) != map.wTextSize)

  {

  GuiMemFree(pBuf);

  close(fd);

  return NULL;

  }

  pBuf[map.wTextSize >> 1] = 0;

  //建立字符串对象

  pTxt = CreateStringDirect(pBuf);

  GuiMemFree(pBuf);

  close(fd);

  return pTxt;

  }

  //定义与字符串相关的数据结构

  #ifndef GUI_STRING_STRUCT

  typedef struct _string

  {

  WORD wWidth; //字符串宽度,字符串输出时的总点阵宽度

  WORD wLength; //字符串长度,不包括‘‘

  WORD * pContent; //字符串内容,以‘‘结尾

  } GUISTRING;

  //结束与字符串相关的数据结构的定义

  #define GUI_STRING_STRUCT

  #endif

  /***[!--empirenews.page--]

  * 功能:

  根据指定的信息直接建立字符串,函数返回字符串指针

  * 参数:

  1.WORD * pContent: 字符串内容

  * 返回:

  成功返回字符串指针

  失败返回NULL

  * 备注:

  ***/

  GUISTRING * CreateStringDirect(WORD * pContent)

  {

  GUISTRING * pStr;

  //尝试为字符串分配内存

  if (!(pStr = GuiMemAlloc(sizeof(GUISTRING))))

  {

  PRINT_INF(CreateStringDirect Err0!);

  return NULL;

  }

  //字符串内容为空,建立一个空字符串对象

  if (!pContent)

  {

  pStr->wWidth = 0;

  pStr->wLength = 0;

  pStr->pContent = NULL;

  return pStr;

  }

  //统计字符串长度

  pStr->wLength = 0;

  pStr->pContent = pContent;

  while (*pStr->pContent++)

  {

  pStr->wLength++;

  }

  //尝试为字符串内容分配内存

  if (!(pStr->pContent = GuiMemAlloc((pStr->wLength + 1) << 1)))

  {

  GuiMemFree(pStr);

  PRINT_INF(CreateStringDirect Err1!);

  return NULL;

  }

  //写入字符串内容

  memcpy(pStr->pContent, pContent, (pStr->wLength + 1) << 1);

  //计算字符串宽度

  if (_StringObjectFill(pStr))

  {

  GuiMemFree(pStr->pContent);

  GuiMemFree(pStr);

  PRINT_INF(CreateStringDirect Err2!);

  return NULL;

  }

  return pStr;

  }

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭