博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(5) Orchard 开发之 Localization and NullLocalizer
阅读量:4982 次
发布时间:2019-06-12

本文共 4647 字,大约阅读时间需要 15 分钟。

  大家都知道在 orchard 中做国际化的时候,直接在代码或 view 中用 T 包上要进行国际化得字符串就行了,

之后 orchard 就会根据你设置得语言文化,寻找到相应得 po 文件来进行 localization。

在 Controller 中你通常定义一个属性,public Localizer T { get; set; } 这里 T 是一个委托。

之后在构造函数中注入一个 NullLocalizer.Instance ,但当你打开 NullLocalizer 时,你发现这个类并没有做什么具体的工作,那国际化究竟是怎么做的呢?

事实上你删掉构造函数中的  T = NullLocalizer.Instance; 不会有任何问题,我也不知道 NullLocalizer 有什么用处??

public static class NullLocalizer {                static NullLocalizer () {            _instance = (format, args) => new LocalizedString((args == null || args.Length == 0) ? format : string.Format(format, args));        }                static readonly Localizer _instance;        public static Localizer Instance { get { return _instance; } }    }

 

下面让我们看看 orchard 中国际化是怎么做的:

具体的类都定义在 Orchard.Framework\Localization\ 下面

首先来看 LocalizationModule 类:

protected override void Load(ContainerBuilder builder) {            builder.RegisterType
().As
().InstancePerDependency(); } protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) { // 通过反射 ,查看你是否定义个一个 public 的 ,名字叫 T 的 ,类型为 Localizer 的委托
// 所以 T 必须是 public 的 名字也不能随便变
var userProperty = FindUserProperty(registration.Activator.LimitType);              if (userProperty != null) {                var scope = registration.Activator.LimitType.FullName;                registration.Activated += (sender, e) => {    // 这里给   registration 这个事件注册了很多个方法                    var localizer = _localizerCache.GetOrAdd(scope, key => LocalizationUtilities.Resolve(e.Context, scope)); // 得到一个 Localizer 对象                    userProperty.SetValue(e.Instance, localizer, null); // 把得到的 Localizer 对象赋给 T ,实际传入的是 Text 类中 Get 方法                    // 实际上 AdminMenu 的 T 也是在这里绑定的, 当你需要一个 Localizer  的实例时这个事件就会被触发,给你的 T 绑定一个方法 (Get)                };            }        }        private static PropertyInfo FindUserProperty(Type type) {            return type.GetProperty("T", typeof(Localizer));        }

下面我们来看看 Text 中的 Get 方法,这才是 T 实际绑定的方法

public LocalizedString Get(string textHint, params object[] args) {   // textHint 就是 T 包裹的字符串            Logger.Debug("{0} localizing '{1}'", _scope, textHint);            var workContext = _workContextAccessor.GetContext();            var currentCulture = workContext.CurrentCulture;  // 得到当前的语言文化,第一次会从数据库中的 Settings_SiteSettingsPartRecord 这个表中读取,随会缓存起来
// 调用 DefaultLocalizedStringManager 中的 GetLocalizedString 方法返回一个本地化的字符串
var localizedFormat = _localizedStringManager.GetLocalizedString(_scope, textHint, currentCulture);             return args.Length == 0                 ? new LocalizedString(localizedFormat, _scope, textHint, args)// 把返回的字符串包装成 LocalizedString 对象,以便显示在页面上                 : new LocalizedString(string.Format(GetFormatProvider(currentCulture), localizedFormat, args), _scope, textHint, args);
}

下面我们来看 DefaultLocalizedStringManager 中的 GetLocalizedString 方法

public string GetLocalizedString(string scope, string text, string cultureName) {            var culture = LoadCulture(cultureName); // 得到当前语言文化            string scopedKey = (scope + "|" + text).ToLowerInvariant();            if (culture.Translations.ContainsKey(scopedKey)) {                return culture.Translations[scopedKey];   // 如果当前 scope 中有 po 文件,直接取出翻译后的字符串            }            string genericKey = ("|" + text).ToLowerInvariant();            if (culture.Translations.ContainsKey(genericKey)) {                return culture.Translations[genericKey];   // 当前工程中找不到 po 文件,再找其他地方,找到则取出翻译后的字符串            }            return GetParentTranslation(scope, text, cultureName);        }

 

orchard 中有一系列的查找路径去找到相应的 po 文件:

const string CoreLocalizationFilePathFormat = "~/Core/App_Data/Localization/{0}/orchard.core.po";        const string ModulesLocalizationFilePathFormat = "~/Modules/{0}/App_Data/Localization/{1}/orchard.module.po";        const string ThemesLocalizationFilePathFormat = "~/Themes/{0}/App_Data/Localization/{1}/orchard.theme.po";        const string RootLocalizationFilePathFormat = "~/App_Data/Localization/{0}/orchard.root.po";        const string TenantLocalizationFilePathFormat = "~/App_Data/Sites/{0}/Localization/{1}/orchard.po";

 

而且 orchard 中做国际化也非常方便:

1) 在要需要国际化的类中定义一个叫 T 的委托  public Localizer T { get; set; }  (view 中直接用 T 包裹就行)

2) 用 T 包裹需要本地化的字符串。

3) 准备好 po 文件,按照指定的格式书写,放到指定的位置,orchard 就能找到并取出了。 po 文件必须是 utf-8 编码,否则会出现乱码,orchard 会用 utf-8 来解析 po 文件

下面我简单翻译 BlogPostAdminController 中的两句提示信息:

把这个 po 文件放到 :\Modules\Orchard.Blogs\App_Data\Localization\zh-CN\orchard.module.po 就行了

   

 

有关 po 文件的格式 和 放置的地方请参考官方网站:

转载于:https://www.cnblogs.com/lesliefang/archive/2013/01/15/2861907.html

你可能感兴趣的文章