(1)模块的本地化和ASP.Net2的本地化不尽相同
建立一个View Module,我拖放了两个控件,一个是常规的Label,还有一个是DNN中的labelcontrol。
利用VS的工具自动生成资源。
它将会在App_LocalResources目录下生成一个对应的resx文件
文件内容如下:
而ascx文件也发生了修改
在Label 中加入了meta:resourcekey=”label1Resource
运行后我们发现Label1的标签并没有发生修改。查阅了相关资料,表明DNN和ASP2.0的Localization是不兼容的。为了证实这一点,我重新修改了代码:
我加入几乎是相同的一行,但是去掉了resourcekey前面的meta。运行
发现第一个Label没有Localization,而第二个由于少了meta就支持了!结论:
DNN的Localization和ASP.Net20有些差异,用自动生成的resx的工具是需要修改调整的。
我们发现在LabelControl也显示了相应的Localization的字符,那时因为我在对应的ascx中加入了不带Meta的resourcekey标签。
(2)作为模块内部的控件的本地化
我们将上述的TestControl变成一个Control
public partial class DesktopModules_ABCTest_TestControl : PortalModuleBase
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
改为
public partial class DesktopModules_ABCTest_TestControl : UserControlBase
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
继承自 UserControlBase。
我们将这个作为一个自定义控件加入到ViewABCTest.ascx中。ViewABCTest.ascx中原有一个Label并定义了其Resourcekey,以及在资源文件中加入Value为“Parent Label”
我们修改一下Module的View模块。
运行,结果发现
作为控件(继承自UserControlBase)的TestControl 并没有像它作为模块(继承自PortalModuleBase)被本地化。
我想起了urlControl,它是一个控件,它有独立的resx本地化文件,它的确能本地化。
我拖放一个urlcontrol的确能够本地化为中文
<asp:label id="lblURLType" runat="server" enableviewstate="False" resourcekey="Type" CssClass="NormalBold"></asp:label>
在resx文件中:
可是这个urlcontrol也使继承自UserControlBase的。他们的差异在哪里呢?
在所有的函数中都找不到踪迹,包括Pageload等等,这个神秘的Localization在哪里呢?最后发现它有一个LocalResourceFile属性:
Public Property LocalResourceFile() As String
Get
Dim fileRoot As String
If _localResourceFile = "" Then
fileRoot = Me.TemplateSourceDirectory & "/" & Localization.LocalResourceDirectory & "/URLControl.ascx"
Else
fileRoot = _localResourceFile
End If
Return fileRoot
End Get
Set(ByVal Value As String)
_localResourceFile = Value
End Set
End Property
估计是这个在作怪,看了几个控件都有这个属性:
我在Solution中查找LocalResourceFile。在几十个结果中抓住了一个“嫌疑犯”。
''' <summary>
''' <para>ProcessControl peforms the high level localization for a single control and optionally it's children.</para>
''' </summary>
''' <param name="c">Control to find the AttributeCollection on</param>
''' <param name="affectedControls">ArrayList that hold the controls that have been localized. This is later used for the removal of the key attribute.</param>
''' <param name="includeChildren">If true, causes this method to process children of this controls.</param>
Friend Sub ProcessControl(ByVal c As Control, ByVal affectedControls As ArrayList, ByVal includeChildren As Boolean, ByVal ResourceFileRoot As String)
在这个函数中对标准的控件进行了翻译(本地化:找到对应的LocalResource文件,取出其值)。比如对于Label:
If TypeOf c Is Label Then
Dim ctrl As Label
ctrl = DirectCast(c, Label)
If value <> "" Then
ctrl.Text = value
End If
End If
这里就是对Lable.Text进行本地化赋值。Value来之何方呢?
Dim key As String = GetControlAttribute(c, affectedControls)
If Not key Is Nothing Then
'Translation starts here ....
Dim value As String
value = Services.Localization.Localization.GetString(key, ResourceFileRoot)
可以理解为value就是在对应的Resource文件中找到该Key。Key又是通过GetControlAttribute函数来提取的,GetControlAttribute函数应该是得到一个控件的属性(集?)。
到此,我们基本明白了,在DNN中自定义控件如果需要本地化,应该实现一个LocalResourceFile只读属性。在对应的文件中加入
public string LocalResourceFile
{
get
{
return DotNetNuke.Services.Localization.Localization.GetResourceFile(this, "TestControl.ascx");
}
}
运行!
结论:
在DNN中自定义控件如果需要本地化,应该实现一个LocalResourceFile只读属性。
好像这个机制改进的余地还是有的,比如用一个Attribute就可以搞定:
[Localizable(“localresourcefile”)]//缺省为“类名.resx”
Public class MyDNNControl:UserControlBase
{
……
}