發表ASP.NET MVC CRUD之路 (2) - Telerik Extensions for ASP.NET MVC Open Source Project一文後,網友亞米斯提了一個問題,Calendar在中文環境下日期顯示會呈現"星星星星星星星",而非"日一二三四五六"! (不知為什麼,看到這場面,我腦海的電影院就會開始播放逃學威龍的片段 XD)。

經實測果真如此:

研判應為元件處理星期名稱邏輯與中文語系的相容問題(似乎是不少日曆元件的通病),追進原始碼CalendarHtmlBuilder.cs: (TGI Open Source :-) )

        public IHtmlNode HeaderCellTag(string dayOfWeek)
        {
            IHtmlNode cell = new HtmlElement("th")
                             .Attributes(new { scope = "col", title = dayOfWeek})
                             .Text(dayOfWeek.Substring(0, 1));
 
            if (dayOfWeek.Length > 3)
                cell.Attribute("abbr", dayOfWeek.Substring(0, 3));
 
            return cell;
        }

依程式邏輯,元件內部只取DayNames第一個字元顯示出來,在英文時會是SMTWTFS,中文就變成星星星星星星星。不想改動核心程式碼(畢竟這段程式必須兼顧各國語系,而目前我只想得出為中文加入特定邏輯分支的鳥做法,就別弄髒了人家的程式),反正已知原理,要解決就不難。

在HomeControler.cs裡加入一段程式重新設定CultureInfo.DateTimeFormat.DayNames為日、一、二、...、六的字串陣列:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Threading;
using System.Globalization;
 
namespace NuGetTelerikMvc.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";
            SetTaiwanCultureInfoDayNames();
            return View();
        }
 
        public ActionResult About()
        {
            return View();
        }
 
        public void SetTaiwanCultureInfoDayNames()
        {
            CultureInfo ci = new CultureInfo("zh-TW");
            ci.DateTimeFormat.DayNames =
                "日 一 二 三 四 五 六".Split(' ');
            Thread.CurrentThread.CurrentCulture = ci;
        }
    }
}

搞定收工!

等一下,住在荖濃溪旁的勞超凡先生Call In,他說更動CultureInfo的日期設定,會影響到所有使用CultureInfo星期設定的程式碼,可能會有副作用。

嗯,若有這一層顧慮,我們可由jQuery從前端下手,加上幾行Code,也能得到相同結果。這種單純從UI修正的做法或許更周到,唯一缺點是jQuery在網頁載入後才更換文字,雖然是極短的時間差,使用者還是可能察覺到畫面變動,但理論上不致構成問題。

@using Telerik.Web.Mvc.UI
<div>
    @Html.Telerik().Calendar().Name("cal")
</div>
<script type="text/javascript">
    $(function () {
        $("thead.t-week-header th:contains('星')").each(function () {
            $(this).text(this.title.substr(2, 1));
        });
    });
</script>
@(Html.Telerik().StyleSheetRegistrar()    
    .DefaultGroup(group => 
    group.Add("telerik.common.css").Add("telerik.default.css")
    .Combined(true).Compress(true)))
@(Html.Telerik().ScriptRegistrar()
    .DefaultGroup(
    group => group.Combined(true).Compress(true)))

搞定收工! (這次是真的了)

[2011-06-07更新]

收工回到家還沒脫外套,馬上又接到布袋的布耀袍先生Call In,說那個jQuery解決方案是山寨版,前端切換到選月份再切回來就破功變回周星星了。先前漏想了AJAX動態互動這段,再調一下程式,連$.telerik.cultureInfo.days也一併換新(程式要放在網頁的最後,才能覆寫ScriptRegistrar()產生的內容),應可解決問題囉!

@using Telerik.Web.Mvc.UI
<div>
    @Html.Telerik().Calendar().Name("cal")
</div>
 
@(Html.Telerik().StyleSheetRegistrar()  
    .DefaultGroup(group => 
    group.Add("telerik.common.css").Add("telerik.default.css")
    .Combined(true).Compress(true)))
@(Html.Telerik().ScriptRegistrar()
    .Globalization(true)
    .DefaultGroup(
    group => group.Combined(true).Compress(true)))
 
<script type="text/javascript">
    $(function () {
        var $t = $.telerik;
        if ($t.cultureInfo) {
            $.extend($t.cultureInfo, { days: "日 一 二 三 四 五 六".split(' ') });
        }
        $("thead.t-week-header th:contains('星')").each(function () {
            $(this).text(this.title.substr(2, 1));
        });
    });
</script>

(小聲地說)搞定收工!(希望這次是真的... orz)


Comments

# by 亞米斯

多謝 黑暗老大 幫凡人解答

# by 亞米斯

jQuery從前端下手 有一個淺在問題 就是當左右換月份 或是 直接按年份 換年時 周星星又會跑出來了 (要在這裡留言 要先通過下方 火星文驗證 好有成就感)

# by Jeffrey

to 亞米斯,緊急再出一個修正版(更新於文末),請參考。

# by 亞米斯

多謝 黑暗兄 說不定有要 加 貢丸滷蛋 或是 加冰 少糖 的 電視機前的朋友(明明就是自己) 覺得畫面上 日一二三 的呈現方式 靠左很不習慣 請$(this).text(this.title.substr(2, 1)); 後面加上 $(this).css("text-align", "right"); @* 設定 right 是因為他CSS設定padding 有點怪 再不改code 的情況下 加上text-align - right 是我的作法 *@

# by 亞米斯

黑暗大 上面的發文幫我刪除好了 這樣作法ajax一跑過 css 設定還是會亂掉

# by Jeffrey

to 亞米斯, 排版格式的部分用CSS霸王硬上弓應該就可以囉! &lt;style type="text/css"&gt; &nbsp; &nbsp;.t-week-header th { text-align: right; } &lt;/style&gt;

# by archer

謝謝你啊,在這裏看到了很多寶藏, 真是太感謝了, Archer

Post a comment