我在使用.resx文件进行本地化时遇到了同样的问题。当进行翻译的人不是程序员时,它们并不起作用。现在,我们在管理区域中有一个翻译页面。效果非常好。
我们仍然没有一个很好的解决方案来处理数据注释,它们仍然使用.resx文件。我已经削减了下面的源代码,以删除任何对我们实际数据库结构或表的引用。
如果数据库中不存在条目,则回退到使用基础的.resx文件。如果.resx文件中没有条目,则我会在发现大写字母时拆分单词(CamelSpace是一个字符串扩展方法)。
最后,根据您的实现方式,您可能需要删除上下文缓存,尤其是如果您正在缓存在进程外。
以下是一些用法示例:
@LanguageDb.Translate("Enter your first name below","FirstNamePrompt")
@LanguageDb.Me.FirstName
@String
.Format(LanguageDb
.Translate(@"You can be insured for
{0} down and {1} payments of {2}"),
Model.Down,Model.NumPayments,
Model.InstallmentAmount)
public class LanguageDb : DynamicObject
{
public static dynamic Me = new LanguageDb();
private LanguageDb() { }
public static string Translate(string englishPhrase, string resourceCode = null)
{
return GetTranslation(englishPhrase, resourceCode) ?? englishPhrase;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = GetTranslation(binder.Name);
return true;
}
private static string GetTranslation(string resourceName, string resourceCode = null)
{
resourceCode = resourceCode ?? resourceName;
if (resourceCode.Contains(" ") || resourceCode.Length > 50)
{
resourceCode = resourceName.GetHashCode().ToString(CultureInfo.InvariantCulture);
}
var lang = (string)HttpContext.Current.Request.RequestContext.RouteData.Values["lang"] ?? "en";
var result = Get(subagent + "_" + lang + "_" + resourceCode, 3600, () =>
{
var context = Get("_context", 30, () => new YourDataContext()) as YourDataContext;
var translation = context.Translations.FirstOrDefault(row => row.lang == lang && row.Code == resourceCode);
if (translation == null)
{
translation = new Lookup {
Code = resourceCode,
lang = lang,
Value = Language.ResourceManager.GetString(resourceName, Language.Culture)
?? resourceName.CamelSpace()
};
context.Translations.Add(translation);
context.SaveChanges();
}
return translation.Value;
});
return result;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
return true;
}
public static T Get<T>(string cacheId, int secondsToCache, Func<T> getItemCallback) where T : class
{
T item = HttpRuntime.Cache.Get(cacheId) as T;
if (item == null)
{
item = getItemCallback();
if (secondsToCache > 0)
{
HttpRuntime.Cache.Insert(
cacheId, item, null, Cache.NoAbsoluteExpiration,
new TimeSpan(0, 0, secondsToCache), CacheItemPriority.Normal, null);
}
else
{
HttpRuntime.Cache.Insert(cacheId, item);
}
}
return item;
}
}