上篇文章我们介绍了

VUE+.NET应用系统的国际化-整体设计思路

系统国际化改造整体设计思路如下:

  1. 提供一个工具,识别前后端代码中的中文,形成多语言词条,按语言、界面、模块统一管理多有的多语言词条
  2. 提供一个翻译服务,批量翻译多语言词条
  3. 提供一个词条服务,支持后端代码在运行时根据用户登录的语言,动态获取对应的多语言文本
  4. 提供前端多语言JS生成服务,按界面动态生成对应的多语言JS文件,方便前端VUE文件使用。
  5. 提供代码替换工具,将VUE前端代码中的中文替换为$t("词条ID"),后端代码中的中文替换为TermService.Current.GetText("词条ID")

今天,我们继续介绍多语言词条服务的设计和实现。

一、多语言词条设计

什么是多语言词条,即代码中需要支持多语言的文本。例如后台提示、前端界面的各类显示元素(Label、Button文字、Tooltips、标题、列表标题等等)。这些内容统一抽象为多语言词条。

多语言词条是产品多语言包的组成部分。支持在不同的语言下,显示对应的文本。

上图中:

I18NTerm代表多语言词条对象,主要描述了多语言词条的各个属性,主要的几个属性有:

/// <summary>
        ///词条的key/// </summary>
        public string Code { get; set; }/// <summary>
        ///词条的名称/// </summary>
        public string Name { get; set; }/// <summary>
        ///原始文本/// </summary>
        public string OriginalText { get; set; }/// <summary>
        ///多语言词条子项/// </summary>
        public List<I18NTermItem> TranslateItems { get; set; } = new List<I18NTermItem>();/// <summary>
        ///隶属的产品/// </summary>
        public string Product { get; set; }/// <summary>
        ///隶属的关键应用/系统/// </summary>
        /// <remarks>
        ///用于批量打包国际化JS文件/// </remarks>
        public string SubSystem { get; set; }/// <summary>
        ///隶属的关键应用/系统编号/// </summary>
        /// <remarks>
        ///用于批量打包国际化JS文件/// </remarks>
        public string SubSystemCode { get; set; }

一条词条,包含多个词条子项I18NTermItem,每一个词条子项,都代表了一种语言的翻译结果

 public classI18NTermItem : CacheElement
{
/// <summary> ///词条ID/// </summary> public string TermID { get; set; }/// <summary> ///语言/// </summary> public string Language { get; set; }/// <summary> ///翻译的文本/// </summary> public string TranslateText { get; set; }/// <summary> ///用户自定义文本/// </summary> public string CustomText { get; set; }public stringGetText()
{
if (string.IsNullOrEmpty(CustomText))
{
returnTranslateText;
}
returnCustomText;
}
}

二、多语言词条管理服务

有了多语言词条对象后,需要增加其对应的多语言词条管理服务,用于对词条的增删查改

先定义一个多语言词条管理的接口II18NTermManageService

public interfaceII18NTermManageService
{
voidAdd(I18NTerm term);void Remove(stringtermId);void AddTerms(List<I18NTerm>terms);void RemoveTerms(List<string>terms);voidUpdate(I18NTerm term);

I18NTerm GetTerm(
stringtermId);

List
<I18NTerm>GetTerms();

List
<I18NTerm> GetTerms(stringsourceId);

List
<I18NTerm> GetTermsByApplication(stringapplicationId);

List
<I18NTerm> GetTermByConditions(string applicationId, string sourceId = null, string sourceLocation = null, string Dimension1 = null, string Dimension2 = null, string Dimension3 = null);

}

这个接口对应的实现中,可以采用EF完成词条数据的持久化操作,在这里不再详细展示了,大家根据需求自行实现即可。

三、多语言词条查询服务

系统在运行时,需要调用词条服务查询各类词条的翻译文本。因此,抽象一个多语言词条查询服务接口II18NTermService

    /// <summary>
    ///词条查询服务接口/// </summary>
    public interfaceII18NTermService
{
/// <summary> ///根据词条编号获取对应的词条翻译/// </summary> /// <param name="termCode">词条编号</param> /// <param name="defaultText">默认值,如果根据编号找不到词条或者词条对应的翻译将返回默认值</param> /// <returns></returns> string GetText(string termCode, stringdefaultText);/// <summary> ///根据词条编号获取对应的词条翻译并格式化输出/// </summary> /// <param name="termCode">词条编号</param> /// <param name="defaultText">默认值,如果根据编号找不到词条或者词条对应的翻译将返回默认值</param> /// <param name="args">包含零个或多个要格式化的对象的对象数组</param> /// <returns></returns> string GetTextFormatted(string termCode, string defaultText, params object[] args);/// <summary> ///根据词条编号获取对应的词条翻译/// </summary> /// <param name="termCode">词条编号</param> /// <param name="language">语言标识</param> /// <param name="defaultText">默认值,如果根据编号找不到词条或者词条对应的翻译将返回默认值</param> /// <returns></returns> string GetTextWithlanguage(string termCode,string language, stringdefaultText);/// <summary> ///根据词条编号获取对应的词条翻译并格式化输出/// </summary> /// <param name="termCode">词条编号</param> /// <param name="language">语言标识</param> /// <param name="defaultText">默认值,如果根据编号找不到词条或者词条对应的翻译将返回默认值</param> /// <param name="args">包含零个或多个要格式化的对象的对象数组</param> /// <returns></returns> string GetTextFormattedWithlanguage(string termCode, string language, string defaultText, params object[] args);/// <summary> ///批量获取词条,注意:此接口不能在特来电生产环境使用。/// </summary> /// <param name="termCodes"></param> /// <returns></returns> Dictionary<string,string> BatchGetText(List<string>termCodes);
}

这个接口的具体实现中,可以增加词条的Redis缓存和内存缓存,调用II18NTermManageService的实现逻辑,从数据库中查询持久化的词条数据。缓存到内存和Redis中,  以提升查询性能。

例如:

 /// <summary>
        ///获取词条翻译/// </summary>
        /// <param name="termCode">词条编号</param>
        /// <param name="defaultText">默认值,当找不到对应的词条时将返回默认值</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public string GetText(string termCode, stringdefaultText)
{
if (string.IsNullOrWhiteSpace(termCode))throw new ArgumentNullException($"Term Code is null, {termCode}");if (Teld.Core.Session.Service.AppContext.Current.Language == null)
{
returndefaultText;
}
string language =T.Core.Session.Service.AppContext.Current.Language.DisplayCode;string key = termCode + "&" +language;if (cache.TryGetValue(key, out varval))
{
returnval;
}
var termItem =termManageService.GetTermItem(termCode, language);if (termItem == null)
{
TermMonitor.NotFound(termCode, language);
returndefaultText;
}
else{string text =termItem.GetText();
cache[key]
=text;returntext;
}
}

以上是多语言词条服务的设计和实现。

分享给大家

周国庆

2023/3/11

标签: none

添加新评论