简体   繁体   中英

Suggestion for database structure for multilanguage

Using PHP 5.x and MySQL 5.x

So I asked a question yesterday about the best way of handling dynamic data in multilanguage, this question is what would be a good solution for the database structure to handle this. I have entries in the database for things like stories. My plan is to store a different version of the story for each language available in a db. So if the site supports english and spanish then in the admin tool they can add a english version of a story and a spanish version of a story.

My thoughts on that was to have seperate tables in the db, one for each language. So one story table for english version, one for spanish and one for whatever other languages. Then on the front end I simply allow the visitor to select what language to view the site in and via variables know what table to query to get that version of the story. But one issue is what if there isnt a spanish version but they selected spanish? Is that a good solution or is there a better way of doing this? Looking for suggestions.

Having multiple tables is really not necessary, unless you plan on having millions of stories... I usually go along with two tables; one for the item and another for the localized item

For example, a story would be like

table "story"

id INTEGER (Primary Key)
creation_date DATE_TIME
author VAR_CHAR(32)
..other general columns..

table "story_localized"

story_id INTEGER (Foreign Key of story.id) \
lang CHAR(2)                               -- (Indexed, unique -- story_id+lang)
content TEXT
..other localized columns..

Performing the query is simply a matter of JOIN ing the two tables:

SELECT s.*, sl.*
  FROM story s
  JOIN story_localized sl ON s.id = sl.story_id
 WHERE s.id = 1         -- the story you're looking for here
   AND sl.lang = 'en'   -- your language here
   -- other conditions here

This configuration gives a few advantages:

  • all your data is in the same table, no need to synchronizing CRUD operations
  • you can add new languages to any story without the need to create yet more tables
  • etc.

** EDIT **

Just as a bonus, here is a "trick" to retrieve a story easily, regardless of the language it's been written into

SELECT *
  FROM (SELECT * 
          FROM story s
          JOIN story_localized sl ON s.id = sl.story_id
         WHERE s.id = {storyId}
           AND sl.lang = {desiredLanguage}    -- example : 'es'
        UNION
        SELECT * 
          FROM story s
          JOIN story_localized sl ON s.id = sl.story_id
         WHERE s.id = {storyId}
           AND sl.lang = {defaultLanguage}    -- example : 'en'
        UNION
        SELECT * 
          FROM story s
          JOIN story_localized sl ON s.id = sl.story_id
         WHERE s.id = {storyId}
         LIMIT 1                              -- ..get the first language found
) story_l
LIMIT 1              -- only get the first SELECTed row found

Will try to fetch the story in the {desiredLanguage} , if the story is not available in that language, try to find it in {defaultLanguage} (ie. the site's default language), and if still nothing found, it doesn't matter which language to fetch the story, then, so fetch the first one found. All in one query, and all you need are 3 arguments: the story id, the desired language, and a default fallback language.

Also, you can easily find out in what language the story is available into with a simple query:

SELECT sl.lang
  FROM story_localized sl
 WHERE sl.story_id = {storyId}

The best way to do this is to store the story as a multi-valued attribute. As @Yanick has shown you. And it would be interfacially better if you populate your language choice element only with those languages in which that story is available.

Another nice approach when it is not a long text: weeks names, monts... in my app I am localizing musical genres, and musical instruments. Use a text field for store json data.

So in my musical "genres" table, there is a text field named "lang". On in I have the following json structure:

{"es_gl":"MARCHA ESPAÑOLA", "es_EN" : "SPANISH MARCH"}

Then using PHP is really easy to get our data from a json structure. Let's say I have a genre on my $genre variable.

$myJSON = json_decode($genre->lang);
echo $myJSON->es_gl // This echoes MARCHA ESPAÑOLA
echo $myJSON->es_es // This echoes SPANISH MARCH

This is good solution when your localization data is not big... like posts or blogs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM