我在ASP.NET MVC 3应用程序上工作,其中为每个国家/地区创建了版本控制中的分支。这使得分支之间的同步变化变得困难,并且随着国家数量的增加,问题将会增加。我已经阅读过有关抽象分支的内容,但从未实际使用它,所以我很难理解如何在一个相当复杂的项目中实现它。
任何人都可以解释如何对抽象是国家的ASP.NET MVC应用程序进行抽象分支,并且应用程序是与服务和数据层有关的n层类型事件吗?
我无法理解的一些事情是:
更新
我不只是谈论语言变化。每个国家/地区的大部分服务层逻辑都是相同的,但在某些关键领域,它们也是不同的,对数据层也是如此。此外,查看内容和布局可能会有所不同,javascript可能会有所不同,控制器逻辑可能会有所不同。
答案 0 :(得分:4)
为什么使用分支来处理本地化?我是疯了。
有几种方法可以在没有每种语言的代码库的情况下进行本地化。
例如。通过在现有视图引擎之上创建自己的视图引擎,您可以从外部程序集加载视图。或者,您可以为每种语言创建一个视图。
您还可以在视图中使用字符串表格进行本地化。
抽象视图的东西。例如。 aspx / cshtml文件,javascript,css等。
Javascripts:我有一个javascript,我的所有逻辑都使用变量而不是字符串来显示消息。通过这种方式,我可以在逻辑脚本之前加载另一个javascript(例如myplugin.sv.js
之前myplugin.js
来获取瑞典语。
aspx / cshtml文件最常用的方法是在其中使用字符串表。
本地化css?为什么呢?
抽象控制器
是吗?为什么?在这里也使用字符串表。
如何管理在一个分支中每个国家拥有所有代码的额外复杂性?
不要使用分支机构。
如何管理每个抽象的功能切换?
啊?
如何在部署时选择适当的国家/地区?
对所有语言使用相同的网站。使用IP地址,Accept-Language
http标头或用户的语言首选项来选择语言。通过设置Thread.CurrentThread.CurrentCulture
和Thread.CurrentThread.CurrentUICulture
如何针对特定国家/地区的功能运行单元测试?
别。逻辑应该是相同的。
更新以回复您的评论
我已经编写了相当多的系统,其中内容被动态加载到应用程序/服务中。即使不同的客户在多租户系统(SaaS)中使用不同的功能,我也从未使用过不同的代码库。
首先,你需要接受两件事:
a)所有内容都是一直加载的(不是谈论翻译,而是功能)。 b)使用适当/标准的本地化方法,但不需要将所有功能都翻译成所有语言。
您所做的只是控制要加载的内容并使用标准技术来获取翻译的功能。通过检查当前语言(Thread.CurrentThread.CurrentCulture.Name
)或任何homebrewn控件来进行控制。
提出新问题以获取更多详细信息。
更新2
我不会依赖IoC来提供特定于语言的功能,而是使用反射和FeatureProvider
类来为我做这些。
例如,假设您有一个名为ISalaryCalculator
的功能,它考虑了所有当地的税收规则等,然后我会创建这样的内容:
// 1053 is the LCID (read about LCID / LocaleId in MSDN)
[ForLanguage(1053)]
public SwedishSalaryCalculator : ISalaryCalculator
{
}
并有一个FeatureProvider来加载它:
public class FeatureProvider
{
List<Assembly> _featureAssemblies;
public T GetLocalFeature<T>()
{
var featureType = typeof(T);
foreach (var assembly in _featureAssemblies)
{
foreach (var type in assembly.GetTypes().Where(t => featureType.IsAssignableFrom(t))
{
var attribute = type.GetCustomAttributes(typeof(ForLanguageAttribute)).First();
if (attribute.LocaleId == Thread.CurrentThread.CurrentCulture.LCID)
return (T)Activator.CreateInstance(type);
}
}
return null;
}
}
获取该功能(针对当前语言):
var calculator = _featureManager.GetLocalFeature<ISalaryCalculator>();
var salaryAfterTaxes = calculator.GetSalaryAfterTax(400000);
答案 1 :(得分:1)
在简单方案(CMS /不多或共享业务逻辑)中,您只处理不同语言的内容,并且:
布局CSS可以位于单独的文件中,并根据用户帐户的区域性或站点区域设置进行拉入。
本地化可以驻留在不同的程序集中 - 每个文化一个或单独的字符串表文件(如上所述)。
在更复杂的场景中,您正在为敏感文化和区域开发应用程序:
您可以使用CSS解决大多数内容问题,但即使您已经提到需要大量自定义视图,您也可以创建一个视图引擎,根据当前文化提取视图文件(例如Index.en-Us .cshtml,Index.ru.cshtml等)
对于不同的业务规则,您必须拥有良好的设计和架构,利用控制反转(例如依赖注入)和模式,例如策略,状态,模板方法等。鉴于您已经具备了这些规则,您将能够在运行时为每个文化创建一个IoC容器项目/程序集,您的UI将不会意识到差异,因为它将简单地消耗这些接口定义的某些服务。
如果您的ViewModel在不同文化之间存在显着差异,那么稍微有点棘手,但如果它们可能您希望在不同的程序集中将每个文化的View + Controller拆分,并再次使用IoC在运行时初始化时配置路由。
显然,部署多文化网站比非文化网站更复杂,无论你走哪条路(每个文化的网站实例或所有文化的一个网站实例),你可能都想投资一些工具来编写脚本多文化部署。
最后 - 关于单元测试 - 如果你已经对每种文化进行了一次基于IoC的设计测试,那就是在运行一组单元测试之前使用和配置正确的依赖容器。
通过这样的设置,开发人员团队应该在相对自包含的环境中工作,因为您的项目将在逻辑上和物理上进行分区,以支持多个团队同时处理单独的部分。无论是在树枝上还是树干/头上都无所谓。当然,如果在一些项目中一切都是一团糟,人们不得不经常合并 - 你处于一个非常糟糕的状态,你的未来并不光明。
最后的话:它不是分支 - 它是关于设计,架构,分区(解决方案,项目和程序集),最后但并非最不重要的是自动化(构建和测试)。
答案 2 :(得分:0)
这有点偏离主题,但我相信你的方向比你需要的更难。本地化内置于ASP.NET中,MVC框架也可以利用它。
短篇小说是你基本上为你想要支持的每种语言制作一个resx。然后,在视图中使用Resources.Global.YourLocalizedStringPropertyName
。
这篇博文是长篇故事。 Scott Hanselman通过javascript本地化和其他更好的观点。它绝对值得一读,并且可能会为您节省大量的工作来使用内置功能而不是自己构建它: