[英]Propel and I18N: fallback to another locale if first is not found
I am currently working on a API allowing users to get some event messages on their devices. 我目前正在开发一个API,允许用户在他们的设备上获取一些事件消息。 Users call my API specifying me their preferred locale (for instance fr_FR
). 用户调用我的API为我指定他们的首选语言环境(例如fr_FR
)。
On the back-office, administrators can choose the languages they want to support. 在后台,管理员可以选择他们想要支持的语言。 Let's assume they choose English and Chinese. 我们假设他们选择英语和中文。 So, they do not support French language. 所以,他们不支持法语。
I am using the Propel I18N behavior to deal with all the translations. 我正在使用Propel I18N行为来处理所有翻译。 In my requests, I am currently doing: 在我的要求中,我目前正在做:
SystemMessageQuery::create()
->joinWithI18N('fr_FR')
->findOne();
It works correctly if I specify an existing locale. 如果我指定现有的语言环境,它可以正常工作。 Yet, if the translation is not available, it returns null. 但是,如果翻译不可用,则返回null。 Sounds logical. 听起来合乎逻辑。
My question is: can I fallback the user on a default locale (in this case, en_US
) if the provided locale is not planned by an administrator? 我的问题是:如果管理员没有计划提供的语言环境,我可以使用默认语言环境(在本例中为en_US
)回退用户吗? If yes, how can I proceed? 如果是,我该怎么办?
I thought to send a prior request to check if the locale exists. 我想发送一个先前的请求来检查语言环境是否存在。 But I do not think it is a good way for performances reasons (especially for an API). 但我不认为这是出于性能原因(特别是API)的好方法。
Any idea? 任何想法?
According to the documentation , there is not such a fallback in Propel. 根据文档 ,Propel没有这样的后备。
What you can try, is the combination of setLocale
and joinWithI18N
. 您可以尝试的是setLocale
和joinWithI18N
的组合。 Something like: 就像是:
$default_locale = 'en_US';
$items = ItemQuery::create()
->joinWithI18n('fr_FR')
->find();
foreach ($items as $item)
{
echo $item->getPrice();
// test if name is translated
if (!$name = $item->getName())
{
// otherwise, try to get the translation with default locale
$item->setLocale($default_locale);
$name = $item->getName(); // one query to retrieve the English translation
}
}
I haven't tested this code but it seems to be a solution. 我没有测试过这段代码,但它似乎是一个解决方案。
Also, have you tried to add two joinWithI18N
(one for en_US
& one for fr_FR
) to see how the query handle it? 此外,您是否尝试添加两个joinWithI18N
(一个用于en_US
和一个用于fr_FR
)以查看查询如何处理它?
Finally, I used the following code: 最后,我使用了以下代码:
public function setLocale($locale = 'en_US', $fallbackEnabled = false)
{
if($fallbackEnabled) {
$localeExists = SystemMessageI18nQuery::create()
->filterByLocale($locale)
->filterById($this->getId())
->count();
if(!$localeExists) {
$locale = SystemMessageI18nQuery::create()
->filterById($this->getId())
->select('locale')
->findOne();
}
}
parent::setLocale($locale);
}
It is not the best solution for performance reasons, but it is functionnal. 它不是出于性能原因的最佳解决方案,但它是功能性的。
Try something like this 尝试这样的事情
public function joinWithI18nFallback($locale=null, $joinType = Criteria::LEFT_JOIN, $default_locale=null)
{
$languages = sfConfig::get('sf_languages');
if(null == $locale)
{
$locale = sfPropel::getDefaultCulture();
}
if(null == $default_locale)
{
$default_locale = sfPropel::getDefaultCulture();
}
$languages[] = $locale;
$languages[] = $default_locale;
$languages = array_unique($languages);
$FallbackQuery = CategoryQuery::create()
->leftJoin('CategoryI18n')
->addJoinCondition('CategoryI18n', "CategoryI18n.Culture IN ('".implode("','", $languages)."')" )
->withColumn('CategoryI18n.Culture', 'CultureDefault')
->addAscendingOrderByColumn("FIELD(category_i18n.culture, '".$locale."', '".implode("','", $languages)."' )")
->where("CategoryI18n.name != ''");
$this->addSelectQuery($FallbackQuery, 'Category')
->join('CategoryI18n', $joinType)
->addJoinCondition('CategoryI18n', 'CategoryI18n.Culture = Category.CultureDefault' )
->with('CategoryI18n')
->groupById();
$this->with['CategoryI18n']->setIsWithOneToMany(false);
return $this;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.