NEKOB-log-E

Play Games, and Follow the Rules

Flower

Posts Tagged ‘locale’

有時候不能相信手冊

嗯….太相信手冊會吃虧的.

這幾天在重新把一些PHP Framework補齊, 重寫之前HDD掛點時損失的一些小lib, 同時把以前用普通寫法做的functin都物件化.

弄到i18n的部份時, 以往是靠大量的variables配合require/include去做, 現在學了gettext就想改成gettext base, 結果災難就來了. 首先是PHP最新的手冊上關於gettext的sample.

  1. <?php
  2. // Set language to German
  3. setlocale(LC_ALL, 'de_DE');
  4.  
  5. // Specify location of translation tables
  6. bindtextdomain("myPHPApp", "./locale");
  7.  
  8. // Choose domain
  9. textdomain("myPHPApp");
  10.  
  11. // Translation is looking for in ./locale/de_DE/LC_MESSAGES/myPHPApp.mo now
  12.  
  13. // Print a test message
  14. echo gettext("Welcome to My PHP Application");
  15.  
  16. // Or use the alias _() for gettext()
  17. echo _("Have a nice day");
  18. ?>

照著做之後, 發現gettext()總是不會給我正確的translations, 從apache, php5, extensions的安裝全都檢查過了, 就是弄不好, 開始懷疑是不是自己的 .mo 檔案做錯了, 去找了GNU gettext examples來依樣畫葫蘆寫了一個a.out來測試, 很奇怪的是用C來寫非常正常, 但是PHP的setlocale永遠給我NULL.

手冊應該不會錯才是. 照著GNU gettext的手冊一切正常, 類似的function在PHP下就總是不行, 照手冊的Sample來測試怎麼會連跑都不能跑呢? 加上沒有debug message, 也沒有任何log可以看, 實在不知道該怎麼辦才好.

心想, 該不會是OS問題? Locale可能跟 OS 支援有關係吧. 找一張舊的Debian CD, 在VMWare下裝好測試, 竟然也是一樣的狀況: setlocale(LC_ALL, "") 正常, 但是setlocale(LC_ALL, "en")就不行.

這時候衛斯理說的話就產生作用了: 當所有可能性都不正確時, 最不可能的答案就是答案.

是的, 正解就是, 手冊錯了!

PHP的setlocale並不會複寫這個session用的locale, 必須要配合putenv把locale設定進去, 但是只用putenv還是不成, 因為後頭的bindtextdomain還是要吃setlocale. 也就是說, bindtextdomain要setlocale, 而setlocale要putenv, 所以一定要先putenv再setlocale, 最後bindtextdomain才能正確的讓gettext運作.

  1. <?php
  2. putenv("LC_ALL=en");
  3. setlocale(LC_ALL, "en");
  4. bindtextdomain("myApp", "./locale");
  5. textdomain("myApp");
  6. ?>

這樣寫才會正常, 順序怎麼換都不行. 盡信書不如無書, 盡信手冊不如去STFG. 唉.