数据库条目的本地化

时间:2018-06-07 16:47:17

标签: c# localization asp.net-core-2.0

我目前正在处理一个项目,您可以在其中存储数据库中的产品列表。每个产品都有名称,描述......现在我要翻译产品名称,描述......

我目前的解决方案是使用转换表,我可以在其中添加所有已翻译的数据库条目,如:

product.Title= result.GetLocalized(x => x.Title, language, _localizedPropertyRepository);

和扩展方法:

public static string GetLocalized<T>(this T entity,
            Expression<Func<T, string>> keySelector, LanguageDTO language, ILocalizedPropertyRepository localizedPropertyRepository)
            where T : Mapping, ILocalizedEntity
        {
...
            resultStr = localizedPropertyRepository.GetLocalizedValue(language, entity.Id, localeKeyGroup, localeKey);
...
        }

您还可以在此处看到类似的示例: https://github.com/nopSolutions/nopCommerce/blob/develop/src/Libraries/Nop.Services/Localization/LocalizationExtensions.cs

我的问题是,我对此并不满意。要使用静态类,以便我可以访问Context或在扩展方法中发送整个注入的对象看起来不是一个好习惯。还有其他方法可以解决这个问题吗?

我也使用AutoMapper,将整个实体映射到DTO。我认为当前的解决方案无法与AutoMapper一起使用。我必须做出类似的事情:

CreateMap<Product, ProductDTO>()
                .ForMember(x => x.Title, opt => opt.???GetLocalized(????));

但我需要GetLocalized中的实体而不仅仅是Property。此外,我无权访问_localizedPropertyRepository或客户的语言。

1 个答案:

答案 0 :(得分:0)

好吧,我花了一天时间,但我得到了一个有效的解决方案。因此,如果其他人遇到同样的问题,这是我的解决方案。我希望它有所帮助:

public class Mapping
{
    [DataMember]
    public long Id { get; set; }
}

[DataContract]
public class ProductDTO: Mapping
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string ShortDescription{ get; set; }
}

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Product, ProductDTO>()
            .ForMember(t => t.Name, opt => opt.ResolveUsing<LocalizationResolver, EntityInfo>(src => new EntityInfo()
            {
                LocaleKeyGroup = "Product",
                LocaleKey = "Name",
                DefaultValue  = src.Name
            }))
            .ForMember(t => t.ShortDescription, opt => opt.ResolveUsing<LocalizationResolver, EntityInfo> (src => new EntityInfo()
            {
                LocaleKeyGroup = "Product",
                LocaleKey = "ShortDescription",
                DefaultValue = src.ShortDescription
            }));
    }
}

public class EntityInfo
{
    public string LocaleKeyGroup { get; set; }
    public string LocaleKey { get; set; }
    public string DefaultValue { get; set; }
}

public class LocalizationResolver : IMemberValueResolver<Mapping, object, EntityInfo, string>
{
    public string Resolve(Mapping source, object destination, EntityInfo sourceMember, string destMember,
        ResolutionContext context)
    {

        context.Items.TryGetValue("Language", out object languageObject);
        context.Items.TryGetValue("Repository", out object repositoryObject);

        ILocalizedPropertyRepository repository = repositoryObject as ILocalizedPropertyRepository;
        LanguageDTO language = languageObject as LanguageDTO;

        if (language == null || repository == null)
        {
            throw new ArgumentNullException($"Language and LocalizationRepository as AutoMapper Parameter");
        }      

        if(source.Id == 0)
        {
            return sourceMember.DefaultValue;
        }
        //Get the value from the DB
        return LocalizationExtension.GetLocalized(sourceMember.LocaleKey, sourceMember.LocaleKeyGroup, sourceMember.DefaultValue, source.Id, language, repository);
    }
}

public static class LocalizationExtension
{
    public static string GetLocalized(string localeKey, string localeKeyGroup, string defaultValue, long entityId, LanguageDTO language, ILocalizedPropertyRepository localizedPropertyRepository)
    {
        var resultStr = String.Empty;

        if (language != null)
        {
            resultStr = localizedPropertyRepository.GetLocalizedValue(language, entityId, localeKeyGroup, localeKey);
        }

        if (string.IsNullOrEmpty(resultStr))
        {
            resultStr = defaultValue;
        }

        return resultStr;
    }

    public static void Localice(IMappingOperationOptions<object, object> opt, LanguageDTO language, ILocalizedPropertyRepository localizedPropertyRepository)
    {
        opt.Items["Language"] = language;
        opt.Items["Repository"] = localizedPropertyRepository;
    }
}

仍然需要优化。方法名称并不完美。 EntityInfo的创建很难看。由于依赖注入,我仍然使用整个存储库对象作为参数。此外,它尝试每次都获得一个本地化的值,这在“默认”语言中是必要的,并且会使整个内容减慢一些。