简体   繁体   中英

Symfony2 Translatable bundle and safest multilingual approach

I have developed a website for a personal project in a specific language on Symfony2. It usually takes a long time for everything to program because I like to follow safe approaches in developing code, even If it's the silliest things. My plan now, is to implement my directory business website - let's say musical instrument companies - so that everyone from all over the world could create an account and register their business.

What I have done, is that I have implemented everything from scratch: A Security bundle, some basic entities like Business {name, location, phone, email, information, etc.}, BusinessCategory {name, information etc.} and some custom but simple relationships between them. The user can successfully register for an account and then register their business. I have also implemented translations for every word or phrase that is being shown on the website by using a locale in config.yml and some custom translations for English and let's say Chinese or Spanish. The user can click on a link "English" or "Spanish" and everything gets translated to selected language and the website alias changes from website.com/en to website.com/es.

My next steps are:

  • I want the user to be able to register in English or Spanish. Right now, there is only one entry for that Business in the mysql database and translations exist only for the website text. I want the user to be able to enter the English data and the Spanish data for the same fields for example the "name" of the business, the address etc. That will need possibly 2 entries with a different locale and the same business.

  • I want the website to align with label translations currently existing with the user's translations. This means that when you choose "spanish" you will get everything translated in Spanish AND the Spanish row for that business.

  • I want to use the domains I have purchased for language If possible: Website.com, Website.es, Website.it etc. I would like someone to enter website.it in the address bar of the browser and get automatically everything in Italian.

My main concerns are:

  • If I use the translatable bundle, an additional row will be created for every business. How will they be connected? I mean, the X business with an ID 1234 will be in Spanish and the same one with name translated to Y will have an ID 1235. How will symfony2 know that these two businesses are the same one in a different locale ?

  • What will happen to the joined tables? The User table is linked to the Business table which is linked to the Group table. If I use the translatable extension for the Business table only, how will it affect the other ones ?

I admittedly hadn't looked deep into this two years ago when I checked it out, so take the answer with a grain of salt. But:

If I use the translatable bundle, an additional row will be created for every business. How will they be connected?

There are several approaches to having multilingual data in the same database.

The first, easiest, and most common, is to manage subtables. In essence, if you have a table called company , you create and manage another table, eg company_translations or something to that order, with company_id and locale fields, that holds the translated fields. At the app level, you then propagate property calls accordingly. Occasionally, the master table will hold the translation for the base locale. One big con here is the extra joins to fetch all of the needed details. Another is that you lose the benefit of collation rules defined at the SQL level.

Another is to toss everything in the same table, while keeping a reference of the locale using a field with that name, and the base locale as some kind of parent_id . The rational here is that eg tags and sectors and whatever else you need will need to be translated anyway, so might as well toss everything in there. But it's admittedly less common. The big con here is that, here too, you lose the benefit of collation rules defined at the SQL level.

Yet another approach is to have different sets of tables prefixed with a locale or living in locale-specific schemas. So a variation of the former without introducing collation-related problems, at the cost of introducing worrying about table prefixes or search paths at the app level.

A last option is to not worry about it at all, and to create separate sets of tables altogether -- in essence, a new app -- for each locale. Whether they're in separate (and independent) schemas or databases matters little. (Fwiw, this is my preferred method; see below.)

If memory serves, Doctrine uses the first of these approaches with the base locale in the master table -- but double check to be sure by testing and looking into the structure of a translated set of tables.

I mean, the X business with an ID 1234 will be in Spanish and the same one with name translated to Y will have an ID 1235. How will symfony2 know that these two businesses are the same one in a different locale ?

See above, but note that this should probably be the least of your worries unless you're building a site for the hispanic population living in the US -- and even then, it's dubious to worry about it imho.

The point to have in mind here is that if you're serving a verbatim copy of your en_US website to es_MX users, you're likely doing something very wrong on the marketing/comm front: You simply don't communicate to the two populations the same way. One argument might cater to one of the populations and put the other one off, eg "Gringos no son bienvenidas". Moreover, you're arguably doing a disservice to your audience if you fallback to serving an unexpected locale when no appropriate translation exists.

What will happen to the joined tables? The User table is linked to the Business table which is linked to the Group table. If I use the translatable extension for the Business table only, how will it affect the other ones ?

See first points. On the plus side, Doctrine's behavior will manage this for you. On the minus side, you're introducing extra joins by using the behavior.

The alternative I'd advise is to use two sets of independent tables and to configure where Doctrine grabs its data based on the session's locale. But this is a very personal opinion.

I'm the author of another php 5.4+ library for doctrine2 that permits to translate entity fields.

Point 1 : Take a look at https://github.com/knplabs/doctrinebehaviors#translatable

Its implementation is similiar to doctrineExtensions that you use (uses listeners too) but the approch is different.

What is being done here is more near from OOP and usual doctrine's oneToMany relations between Buisness and BuisnessTranslation .

The correct tranlsation retrieval is then done using simple API stored in a trait.

Point 2 : Use the native _locale handling of symfony2 by decalring this placeholder in your urls: http://symfony.com/doc/current/book/translation.html#the-locale-and-the-url

Point 3 : use host config fo routing for defininig your _locale placeholder

http://symfony.com/doc/2.2/components/routing/hostname_pattern.html

Concern 1 : If you do correct relational data, you should not have 2 separate rows that represent the same entity. You should have a Buisness entity that has many BuisnessTranslations (one for each locale).

This BuisnessTranslation table would contain only the data specific to a locale (name, description, ...)

Concern 2 : you will have to join Buisness and BuisnessTranlsation tables together to get the whoe data.

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