缺少语言后备的mysql翻译表 [英] mysql translation tables with missing language fallback

查看:80
本文介绍了缺少语言后备的mysql翻译表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的数据库结构:

I have a database structure like this:

国家/地区

Countries

CREATE TABLE IF NOT EXISTS `countries` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(2) COLLATE utf8_unicode_ci NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UNIQ_5D66EBAD77153098` (`code`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

国家/地区语言

Countries Language

CREATE TABLE IF NOT EXISTS `country_languages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `language_id` int(11) DEFAULT NULL,
  `country_id` int(11) DEFAULT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `IDX_1532561982F1BAF4` (`language_id`),
  KEY `IDX_15325619F92F3E70` (`country_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

语言

CREATE TABLE IF NOT EXISTS `languages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `iso` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1',
  `is_primary` tinyint(1) DEFAULT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UNIQ_A0D153795E237E06` (`name`),
  UNIQUE KEY `UNIQ_A0D1537961587F41` (`iso`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

以及语言表的数据:

id    name        iso
----------------------
1     English     en
2     German      de
3     Italian     it

国家表:

id    code
----------------
1     ie

国家语言表

id    country_id    language_id    name
----------------------------------------------
1     1             1              Ireland in English
2     1             2              Ireland in German

我正在尝试编写一个查询,该查询将返回以下结果以便能够显示它. (如果可能的话)

I am trying to write a query that will return the following result in order to be able to display it. (if possible)

(Language)          (Country name)
English             Ireland in English
German              Ireland in German
Italian             #NULL OR EMPTY STRING

第二步,我试图了解是否可以将例如英语设置为默认语言,并且当不存在ID为3(意大利语)的语言的内容时,默认值应作为以下内容回退:

And second I am trying to understand if it is possible to set for example english as the default language and when content for language with id 3 (Italian) is not present the default should fallback in as a result like this:

(Language)          (Country name)
English             Ireland in English
German              Ireland in German
Italian             Ireland in English #please note language id is 3 -> Italian.

推荐答案

好,因此以下查询可能无需子查询而是使用联接来完成.我相信查询优化器可以做到这一点,但是我不太确定.

okay, so the following query can probably be done without a subquery but with a join instead. I'd trust the query optimizer does this, but I wouldn't be too sure.

SELECT l.name as language,
       (SELECT cl.name 
        FROM country_languages cl 
        WHERE cl.country_id=[the wanted country id]
        ORDER BY cl.language_id=l.id DESC,
                 cl.language_id=1 DESC
        LIMIT 1) as country_name
FROM languages l

在此版本中,lan​​guage_id 1用作首选的后备,您可能会以类似的方式添加更多语言.使用FIND_IN_SET代替二阶条件也可以(FIND_IN_SET(cl.language_id,'1,2,3') DESC或您想要的任何顺序).

In this version language_id 1 is used as the prefered fallback, you could probably add more languages in a similar manner. Using FIND_IN_SET instead as a second order criterion would work as well (FIND_IN_SET(cl.language_id,'1,2,3') DESC or whatever order you'd prefer).

当然,此查询现在针对的是固定的country_id.可以以类似的方式将其扩展到具有另一个联接的多个国家:

Of course this query right now is for a fixed country_id. It could be extended in a similar manner for multiple countries with another join:

SELECT l.name as language,
       (SELECT cl.name 
        FROM country_languages cl 
        WHERE cl.country_id=c.id 
        ORDER BY cl.language_id=l.id DESC,
                 cl.language_id=1 DESC
        LIMIT 1) as country_name
FROM countries c
JOIN languages l

子查询的另一种选择是两次加入country_languages,然后选择第一个不为null的(可能是更干净的解决方案之一):

an alternative to subqueries would be to join the country_languages twice, and just select the first one not being null (which is probably one of the cleaner solutions):

SELECT l.name as language, 
       COALESCE(first.name, second.name) as country_name
FROM countries c
JOIN languages l
LEFT JOIN country_languages first ON 
        (first.country_id=c.id AND first.language_id=l.id)
LEFT JOIN country_languages second ON
        (second.country_id=c.id AND second.language_id=1)

如果语言ID 1是您的后备语言.还可以扩展它以提供多种后备语言...

If language id 1 is your fallback language. This can be expanded as well to provide multiple fallback languages ...

这篇关于缺少语言后备的mysql翻译表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆