修正Telerik MVC Calendar星期顯示問題
發表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)