我知道,我有一个问题已被广泛讨论,但在我看来,还有一个方面需要澄清。
我正在创建一个带有多语言数据库的 Web 应用程序,我已经找到了一些好的实践文章(例如 this )并在堆栈溢出中找到了答案,例如 this .
所以我决定使用一个包含我的项目 ID 的主表和另一个包含每个项目的翻译的表,例如
Content
ContentTranslation
或
Category
CategoryTranslation
等等。
现在我在做什么?我只是从数据库中获取包含所有翻译的项目,然后遍历每个项目以根据当前用户的本地查找正确的翻译,如果找到正确的本地,我将设置为页面翻译的主要对象渲染,否则我只会得到标记为“默认”的翻译。
但是,如果有大量对象和翻译,服务器响应时间可能会增加,即使用户可能没有注意到,我也不希望这样。
那么,这个用例也有什么好的做法吗?例如,一些特定的查询说“选择带有语言环境“它”的翻译,但如果你没有找到它,只需获取设置了“默认”标志的翻译?
现在,我将 Spring MVC 与 Hibernate 和 JPA 结合使用(通过 JPARepository)。
我的所有对象都扩展了我以这种方式创建的基本 Translatable 类
@MappedSuperclass
public abstract class Translatable<T extends Translation> extends BaseDTO {
private static final long serialVersionUID = 562001309781752460L;
private String title;
@OneToMany(fetch=FetchType.EAGER, orphanRemoval=true, cascade=CascadeType.ALL)
private Set<T> translations = new HashSet<T>();
@Transient private T currentLocale;
public void addLocale(T translation, boolean edit) {
if (!edit)
getTranslations().add(translation);
}
public void remLocale(String locale) {
T tr = null;
for (T candidate: getTranslations()) {
if (candidate.getLocale().equals(locale))
tr = candidate;
}
getTranslations().remove(tr);
}
public T getLocaleFromString(String locale) {
if (locale == null)
return null;
for (T trans: translations) {
if (trans.getLocale().equals(locale))
return trans;
}
return null;
}
public T getDefaultLocale() {
for (T tr: translations) {
if (tr.isDefaultLocale())
return tr;
}
return null;
}
public Set<T> getTranslations() {
return translations;
}
public void setTranslations(Set<T> translations) {
this.translations = translations;
}
public T getCurrentLocale() {
return currentLocale;
}
public void setCurrentLocale(T currentLocale) {
this.currentLocale = currentLocale;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
因此,在我的 Controller 中,我遍历翻译,找到具有正确语言环境的翻译并填充“currentLocale”属性,在我的页面中,我只是采用它,用户会按预期获得正确的语言。
我希望我说得清楚而不是乱七八糟,但是如果您需要更多信息,我很乐意告诉您更多信息。
最佳答案
一些注意事项:
在我的应用程序中,我使用两种不同的方法来加载多语言数据,具体取决于用例:
如果用户输入数据或编辑现有数据(例如带有翻译的产品),我使用的方法与您在上面的问题中显示的方法相同,例如:
public class Product
{
public int ID {get; set;}
public string SKU {get; set;}
public IList<ProductTranslation> Translations {get; set;}
}
public class ProductTranslation
{
public string Language {get; set;}
public bool IsDefaultLanguage {get; set;}
public string Title {get; set;}
public string Description {get; set;}
}
即我将让 OR-mapper 加载附加了所有翻译的产品实例。然后,我遍历翻译并选择需要的翻译。
在这种情况下,主要是前端代码,我通常只是向用户显示信息(最好是用用户的语言),我使用的是不同的方法:
首先,我使用的是不同的数据模型,它不支持/不知道多重翻译的概念。相反,它只是以当前用户的“最佳”语言表示产品:
public class Product
{
public int ID {get; set;}
public string SKU {get; set;}
// language-specific properties
public string Title {get; set;}
public string Description {get; set;}
}
为了加载这些数据,我使用了不同的查询(或存储过程)。例如。要以 @Language 语言加载 ID 为 @Id 的产品,我将使用以下查询:
SELECT
p.ID,
p.SKU,
-- get title, description from the requested translation,
-- or fall back to the default if not found:
ISNULL(tr.Title, def.Title) Title,
ISNULL(tr.Description, def.Description) Description
FROM Products p
-- join requested translation, if available:
LEFT OUTER JOIN ProductTranslations tr
ON p.ID = tr.ProductId AND tr.Language = @Language
-- join default language of the product:
LEFT OUTER JOIN ProductTranslations def
ON p.ID = def.ProductId AND def.IsDefaultLanguage = 1
WHERE p.ID = @Id
如果存在该语言的翻译,这将返回所请求语言的产品标题和描述。如果不存在翻译,则返回默认语言的标题和描述。
关于java - 多语言数据库,默认回退,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26765175/
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我