2012年5月16日 星期三

多國語言插件

這是採用 CxxlMan 程式庫的機動化元件所做的插件,可以幫你寫的程式或其他插件可以有提供多國語言文字的處理功能,文字來源由語言轉換檔提供,依多國語言的需求編製相應的語言轉換檔,語言轉換檔只是一般的文字檔(但須是 Unicode 編碼)。

下載點:多國語言插件(7-01-2012 更新).7z

內含使用說明、原始檔和範例程式,請自行參考

在這僅就 "Regional language retrieval.tbl" 和 "Locale name abbreviation.tbl" 兩個檔案的原由做個說明。原本這個插件是要藉由 setlocale(LC_CTYPE, "") 回傳的 Locale Name 來自動匹配語言轉換檔,只要程式使用者所使用 Windows 的語系有支援的語言轉換檔存在就用它做轉換,若不行就使用原來的文字。

本來是這麼簡單,但後來發現 setlocale(LC_CTYPE, "") 在 WinXp 和 Win7 傳回的 Locale Name 竟不一樣。setlocale(LC_CTYPE, "") 傳回的是長字串的 Locale Name,我知還有一種簡寫版的 Locale Name,比如 CHT、CHS、JPN...等,把它做為 setlocale() 第二個參數會傳回相對應的長字串 Locale Name,因此只要寫個程式在 WinXP 和 Win7 跑一遍就可以收集長字串 Locale Name 和 短字串 Locale Name 的對應表,藉由這個對應表也一樣可以自動匹配語言轉換檔。

但須有一份 短字串 Locale Name 的列表才行,上網找啊找,終於找到了http://www.microsoft.com/resources/msdn/goglobal/default.mspx,注意 Local language name 那一項,還是使用適用於該語系的文字,所以我就把該表的 Language Country/Region 、Local language name 和 Language name abbreviation 三項做成 "Regional language retrieval.tbl" 這個檔案,可以做為程式的使用者手動選擇語系之用。
有了 "Regional language retrieval.tbl",其中包含短字串的 Locale Name,就可以用以下的程式碼,在 WinXP 和 Win7 都跑一遍,得到了 "Locale name abbreviation.tbl" 可以讓程式自動選擇語系之用

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <CXXLCOMPOSITE.HPP>
#include <wifstreambuf.h>

using namespace std;
using namespace CxxlMan;

#define StrPkg string_wrapper<wchar_t>

int main(int argc, char* argv[])
{
  Smart_Ptr<cxxlComposite<StrPkg,true> > // LocaleName 名稱不可以重複
    LocName2abbreviation(new cxxlComposite<StrPkg,true>(L"Locale name abbreviation table") );

  // 若 ocale name abbreviation.tbl 存在先載入原有的資料
  {
    wifstreambuf wfin_buf(L"Locale name abbreviation.tbl");
    if(wfin_buf.isOpen())
    {
      wistream wfin(&wfin_buf);
      LocName2abbreviation = UniqueTxtCompositeImport(wfin);

      if(LocName2abbreviation.isNULL())
      {
        cout << "Locale name abbreviation.tbl 不正確" << endl;
        return 0;
      }
    }
  }

  Smart_Ptr<cxxlComposite<StrPkg,true> > Regional_language_retrieval(NULL);
  wifstreambuf wfin_buf(L"Regional language retrieval.tbl");
  if(wfin_buf.isOpen())
  {
    wistream wfin(&wfin_buf);
    Regional_language_retrieval = UniqueTxtCompositeImport(wfin);
    if(Regional_language_retrieval.isNULL())
    {
      cout << "Regional language retrieval.tbl 不正確" << endl;
      return 0;
    }
  }
  else
  {
    cout << "Regional language retrieval.tbl 不存在" << endl;
    return 0;
  }

  Smart_Ptr<cxxlList<cxxlComposite<StrPkg,true> > >
    Regional_language_retrieval_List = Regional_language_retrieval->cxxlList_Create();

  Regional_language_retrieval_List->ResetPT(toHead);
  for(Smart_Ptr<cxxlComposite<StrPkg,true> > p=(*Regional_language_retrieval_List)++;
    p.isNULL() == false;
    p = (*Regional_language_retrieval_List)++)
  {
    UNICODE_String 
      Language_name_abbreviation(p->GetObj(L"Language_name_abbreviation"));
    UNICODE_String LocaleName = _wsetlocale(LC_CTYPE, Language_name_abbreviation);

    if(LocaleName.isNULL() == false)
      // LocaleName 若有重複自動略過
      LocName2abbreviation->Add(Language_name_abbreviation, LocaleName);
  }

  wostringstream wsout;
  UniqueTxtCompositeExport(wsout,LocName2abbreviation);

  FILE * pFile = fopen("Locale name abbreviation.tbl", "wb");

  if(pFile == NULL)
    cout << "無法寫入 Locale name abbreviation.tbl" << endl;

  fwrite(wsout.str().c_str(), sizeof(wchar_t), wsout.str().length(), pFile);
  fclose(pFile);

  return 0;
}



沒有留言:

張貼留言