也谈MOSS控件中使用多语言
今天看了博客园的RSS,看到夏天的感觉写了关于MOSS国际化编程(多语言)的问题,春节前我在写一些通用控件时也遇到了一些问题,在这也分享一下。相同的我就不说了,我只说一下我不同的地方, 主要是关于部署的问题。
首先,简单说说取资源的方法
我建了两个资源文件,分别是ResourceFileName.resx(默认使用英文),ResourceFileName.zh-ch.resx(中文),之所以不写ResourceFileName.en-us.resx是因为当没有找到当前所需要的语言时,可以默认使用ResourceFileName.resx文件。
在取资源的时候,我选择使用了HttpContext.GetGlobalResourceObject方法并把它包装在一个Helper类的静态方法里面,方便其它地方的调用,详细代码如下:
调用时:
第二,说说关于部署的问题
在开发时,代码编译后把RESX文件与DLL拷到相应目录后就可以正常工作了,但由于我开发的是通用控件,不能使用手工部署,必须打包成WSP并在多个应用程序下都可以使用。恰恰是由于我写的resx文件是放在应用程序的App_GlobalResources文件夹下的,而打包成解决方案(wsp)的manifest并不支持把文件放到该文件夹下,当时我是打算改变取资源的方法,仅使用DLL文件形式的资源文件,因为dll文件我可以通过wsp部署到应用程序的bin或者GAC中,但最后考虑到使用起来的确不方便,还是放弃了这一想法,并集中火力,想方设法把文件拷到App_GlobalResources下。
查阅了很多资料后,发现App_GlobalResources这个文件夹是在当应用程序建立时创建的(废话,嘻嘻),而App_GlobalResources文件夹里面的文件是从“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\Resources”中拷贝过来的,而且仅当应用程序建立时才把文件全部拷贝过来,应用程序建立后,无论源文件夹怎样改变,应用程序的App_GlobalResources文件夹也不会得到同步。
那么,wsp不能拷贝文件到App_GlobalResources下,源文件夹也不会自动与应用程序的App_GlobalResources同步,就是说MOSS本身是不支持App_GlobalResources下文件的部署的,而我们偏偏就需要部署文件到它下面。
经过上面的分析,我们可以做的事就只剩下一样的,利用eventhandler使用代码拷贝文件。要利用代码拷贝文件要考虑几件事情,首先是当wsp部署时要把文件拷贝过去,当wsp卸载时,要把文件删除;其次是当有多台前端服务器时要一起拷贝,一起删除。
我在这里利用了MOSS的SPJobDefinition类(从一个老外那查到的资料),把多台服务器一起执行的工作交给MOSS自己去处理 ,我们只要写做拷贝与删除的代码并写在SPJobDefinition中,在恰当的时候启动一个SPJob:
因为我是写一个通用控件,可以通过Feature来控件是启用该控件,当在启用该控件时,我便可以启动那个拷贝文件的SPJob类来拷贝需要的文件。
下面是详细的代码
1.从SPJobDefinition下继承下来的“拷贝文件工作类”:
因为是项目的原因,只能把部分代码拷下来,其它的代码就不再详细说了,代码中也只写了拷贝文件,没写删除文件,只要根据提示加上相应的代码就行了。
另外,这是利用了MOSS的SPJOB来实现的,而spjob是使用wss的Timer服务调度的,在Feature启用时,文件的拷贝会有一定的延迟,默认延迟的时间不长,就几秒钟的时间。
首先,简单说说取资源的方法
我建了两个资源文件,分别是ResourceFileName.resx(默认使用英文),ResourceFileName.zh-ch.resx(中文),之所以不写ResourceFileName.en-us.resx是因为当没有找到当前所需要的语言时,可以默认使用ResourceFileName.resx文件。
在取资源的时候,我选择使用了HttpContext.GetGlobalResourceObject方法并把它包装在一个Helper类的静态方法里面,方便其它地方的调用,详细代码如下:
1/// <summary>
2 /// 全局资源文件名
3 /// </summary>
4 internal const string ResourceFileName = "ResourceFileName";
5
6/// <summary>
7 /// 返回全局资源
8 /// </summary>
9 /// <param name="key">资源关键字</param>
10 /// <returns></returns>
11 public static object GetGlobalResource(string key)
12 {
13 return GetGlobalResource(ResourceFileName, key);
14 }
15 /// <summary>
16 /// 返回全局资源
17 /// </summary>
18 /// <param name="resourceFileName">资源文件名</param>
19 /// <param name="key">资源关键字</param>
20 /// <returns></returns>
21 public static object GetGlobalResource(string resourceFileName, string key)
22 {
23 try
24 {
25 return HttpContext.GetGlobalResourceObject(resourceFileName, key, Thread.CurrentThread.CurrentCulture);
26 }
27 catch (Exception ex)
28 {
29 Log(ex.Message, EventLogEntryType.Warning);
30 return string.Empty;
31 }
32 }
2 /// 全局资源文件名
3 /// </summary>
4 internal const string ResourceFileName = "ResourceFileName";
5
6/// <summary>
7 /// 返回全局资源
8 /// </summary>
9 /// <param name="key">资源关键字</param>
10 /// <returns></returns>
11 public static object GetGlobalResource(string key)
12 {
13 return GetGlobalResource(ResourceFileName, key);
14 }
15 /// <summary>
16 /// 返回全局资源
17 /// </summary>
18 /// <param name="resourceFileName">资源文件名</param>
19 /// <param name="key">资源关键字</param>
20 /// <returns></returns>
21 public static object GetGlobalResource(string resourceFileName, string key)
22 {
23 try
24 {
25 return HttpContext.GetGlobalResourceObject(resourceFileName, key, Thread.CurrentThread.CurrentCulture);
26 }
27 catch (Exception ex)
28 {
29 Log(ex.Message, EventLogEntryType.Warning);
30 return string.Empty;
31 }
32 }
调用时:
HelperClassName.GetGlobalResource("KeyName").ToString();
第二,说说关于部署的问题
在开发时,代码编译后把RESX文件与DLL拷到相应目录后就可以正常工作了,但由于我开发的是通用控件,不能使用手工部署,必须打包成WSP并在多个应用程序下都可以使用。恰恰是由于我写的resx文件是放在应用程序的App_GlobalResources文件夹下的,而打包成解决方案(wsp)的manifest并不支持把文件放到该文件夹下,当时我是打算改变取资源的方法,仅使用DLL文件形式的资源文件,因为dll文件我可以通过wsp部署到应用程序的bin或者GAC中,但最后考虑到使用起来的确不方便,还是放弃了这一想法,并集中火力,想方设法把文件拷到App_GlobalResources下。
查阅了很多资料后,发现App_GlobalResources这个文件夹是在当应用程序建立时创建的(废话,嘻嘻),而App_GlobalResources文件夹里面的文件是从“C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\Resources”中拷贝过来的,而且仅当应用程序建立时才把文件全部拷贝过来,应用程序建立后,无论源文件夹怎样改变,应用程序的App_GlobalResources文件夹也不会得到同步。
那么,wsp不能拷贝文件到App_GlobalResources下,源文件夹也不会自动与应用程序的App_GlobalResources同步,就是说MOSS本身是不支持App_GlobalResources下文件的部署的,而我们偏偏就需要部署文件到它下面。
经过上面的分析,我们可以做的事就只剩下一样的,利用eventhandler使用代码拷贝文件。要利用代码拷贝文件要考虑几件事情,首先是当wsp部署时要把文件拷贝过去,当wsp卸载时,要把文件删除;其次是当有多台前端服务器时要一起拷贝,一起删除。
我在这里利用了MOSS的SPJobDefinition类(从一个老外那查到的资料),把多台服务器一起执行的工作交给MOSS自己去处理 ,我们只要写做拷贝与删除的代码并写在SPJobDefinition中,在恰当的时候启动一个SPJob:
因为我是写一个通用控件,可以通过Feature来控件是启用该控件,当在启用该控件时,我便可以启动那个拷贝文件的SPJob类来拷贝需要的文件。
下面是详细的代码
1.从SPJobDefinition下继承下来的“拷贝文件工作类”:
1public class DeployGlobalResources : SPJobDefinition
2 {
3 Fields
7
8 Constructors
29
30 Job Handling
65 }
2. Feature的事件处理类2 {
3 Fields
7
8 Constructors
29
30 Job Handling
65 }
1public class GlobalResourcesEventReceiver : SPFeatureReceiver
2 {
3 Constants
9
10 Events
59 }
2 {
3 Constants
9
10 Events
59 }
因为是项目的原因,只能把部分代码拷下来,其它的代码就不再详细说了,代码中也只写了拷贝文件,没写删除文件,只要根据提示加上相应的代码就行了。
另外,这是利用了MOSS的SPJOB来实现的,而spjob是使用wss的Timer服务调度的,在Feature启用时,文件的拷贝会有一定的延迟,默认延迟的时间不长,就几秒钟的时间。