Multilingual Site in Zend Framework - php

i am working on a site to include Multilingual Support.
I can translate strings using Zend_Translate but what about the content??
For example do i have to add multiple records for same product's for each language? Or is there any other way?
I am new to multilingual please help.
Thanks in advance.
--- Addition -----------------------------
Ok, i decided to use a mixed solution to use google translation api and storing it in database for further editing. So what sould be the structure of database to store translations???
Should i save translations of different language in same table as parent record. i.e. for product in product table with an extra column to identity language.
A generalized single table to store all translations of all tables. e.g. translations (id bigint,table_name vc(50),table_id bigint, langugae, column_name vc(50), translation )
should i save records in related tables

Few possible approaches:
Using gettext (or software like Poedit) to extract the data from the content. Possible with variable interpolation.
Creating view filter like described in: Zend Framework and Translation
Have separate content of the data in the database.
If you store the content in markup (e.g. Markdown) format, anyone can translate it easily. It's easy to create search engine in different languages.
Seems the third approach requires the most efforts, but it is worth.
Update after comment
I assume you store your product data in the database, in fields like:
- product_data
-- id
-- price
-- name
-- description
-- etc…
So you should modify it, to add fields for translated strings in each language:
- product_data
-- id
-- price
- product_data_translations
-- product_id
-- language (e.g. en)
-- name
-- description
-- etc
Then you can easily build SQL queries to extract translated data where product_id=x and language="fr".
You may use also Doctrine I18N to do it for you automatically.
You need to translate the content manually (or automate the translation using Google API), but then, you can easily index it using for example Zend_Search_Lucene.

Related

Approaches for user extensible entities with a relational database (mySQL)

We have a php/mysql system with about 5 core entities. We now need to add the ability for customers to create custom fields for some of these entities on a per project basis.
They would contain a label, key, type, default value, and possible allowed values.
This is so they could add a custom date field, or a custom dropdown to the UI and save this value against the specific entity.
What is the best approach for storing this kind of data in a mySQL database? I need to store both the config for the field, and then the current value for a specific entity.
I've had a look at various options here.. https://ayende.com/blog/3498/multi-tenancy-extensible-data-model
But this is not really at a tenancy level, more a project level.
I was thinking...
A CustomFields table to hold the configuration of a field against an entity type and project id.
A CustomFieldValues table to hold the value saved against the field - a row per field ( entity_id | field_id | field_value)
Then we create relationships between the entities and these custom values when retrieving the entities.
The issue with this is that there will be as many rows in the Values table as there are custom fields - so saving a entity will result in X extra rows. On top of that, these are versioned, so once a new version is created, there will be another X rows created for that new version.
Also, you can't index the fields on name, joins would become pretty complex i think as you have to join to the configuration and the values to build the key value pair to return against the entity, and how would you select based on a custom field name, when the filed name was actually a value?
I don't want to add dynamic columns to the table, as this will affect ALL the entites in the whole system - not just the ones in the current client / project.
The other option is to store the values in a JSON column.
This could be on the entity row itself customFields or similar. This would prevent the extra rows per field, but also has issues with lack of indexing etc, and still need to join to the config table. However, you could perform queries by the property name if the key=value was stored in the JSON... WHERE entity.customFields->"$.myCustomFieldName" > 1.
Storing the filed name in the json does mean you cannot change it once created, without a lot of pain.
If anyone has any advice on approaches for this, or articles to point me at that would be much appreciated - Im sure this has been solved many times before....
JSON records: No! A thousand times no! If you do that, just wait until somebody actually uses your system for a few tens of millions of records, then asks you to search on one of your extra fields. Your support people will curse your name.
Key-value store. Probably yes. There's a very widely deployed existence proof of this design: WordPress. It has a table called wp_postmeta, containing metadata fields applying to wp_posts (blog pages and posts). It's proven successful.
You will need to do some multiple joining to use this stuff. For example, to search on height and eye-color, you'd need
SELECT p.person_id, p.first, p.last, h.value height, e.value eye_color
FROM person p
LEFT JOIN attrib h ON p.person_id = h.person_id AND h.key='eye_color'
LEFT JOIN attrib e ON p.person_id = e.person_id AND e.key='height'
WHERE e.value='green' and CAST(h.value AS INT) < 160
As the CAST in that WHERE clause shows, you'll have some struggles with data type as well.
You'll need LEFT JOIN operations in this sort of attribute lookup; ordinary inner JOIN operations will suppress rows with missing attributes, and that might not work for you.
But, if you do a good job with indexes, you'll be able to get decent performance from this approach.
The table structure envisioned in my example doesn't have your table describing each additional field, but you know how to add that. It also doesn't have explicit support for multi-project / multitenant data separation. But you can add that as well.

search in appropriate Mysql fields based on current App Locale in laravel

In a multilingual website I have these fields for Products table
product_id
title_fa
title_en
title_ar
desc_fa
desc_en
desc_ar
.
.
.
Now I want to search in (for Example) title fields based on Current laravel Locale.
I know that we can use this way :
$products = Product::where('title_'.App::getLocale(),'LIKE' , '%'.$data['search_value'].'%');
But I thinks that is not clean and easy for number of large fields is not suitable.
I'm looking for a way that was and simple as normal search field and then laravel search based on that field in background According to current App Locale like:
$products = Product::where('title','LIKE' , '%'.$data['search_value'].'%');
How Can I do that and what is best way ?
Hi if you want really easy way for search products than use this following laravel multi language package
https://github.com/dimsav/laravel-translatable
in this package you have to create 2 tables one Product and Product_translate, product table will have your basic product info, translate will have language data, in product_translate table you can use search queries, ease is table column name will remain same in where you have use language filter.

Using Views for Multilingual Database

This is a subject that has been discussed multiple times and it always depens on the situation, but I like to share my idea.
Im building a new CMS that must support multilingual applications and can be installed behind existing applications.
The solutions I know and found are:
[Product]
id
price
name_en
name_de
name_fr
only getting the fields you need in your language.
or using mutliple tables like:
[product]
id
price
[languages]
id
tag
[product_translation]
product_id
language_id
name
Joining the correct language
Both situations work and have its pro's and cons. Based on your choice you have to rewrite your query's.
my idea:
[product]
id
price
name
[product_translations]
product_id
language_id
name
[product_es_view]
id -- references the product table
price -- references the product table
name -- references the translation table
Now the idea is that you create a view for every language, but the view is identical to the product table.
Why?
With this setup I can make non-multilingual sites, multilingual without editing the existing model/table. Now the only thing I have to do in my code is use another table and i get a translated version of my model (in php it could be done by adding a simple trait to your model). With SQL server and Mysql you can use updateable views which save the value's in the referenced tables.
I love to hear what you guys think of the idea, and most of all what the biggest cons are of using views for this problem ?
I prefer the second option where every entity is in its own table. If you use product_es_view then it may be easier but less clean code.
Adding new languages should usually not include adding new database tables. Adding new row to languages tables is better.

Database concept multilanguage

I want to create a site in PHP with cakephp that users can insert product manually.
The problem is for the multilanguage because I can have into my site users from all over the world and the product 'apple' in italian for example is 'mela'.
Consider that I can have many many data!
Then i have some solution for the database:
Create a table products with an id
Create a table product_aliases where I have an id the id of product language and the text(ex. apple)
In this mode users can enter into 'apple', translate ad I insert a new line into product_aliases with same id product different language and different text but same product
Define 5 language and create a table with more fields (title_en, title_it, title_es...) the translation is in the same record
Only one table but restricted language
Create a table products with an id
Create a table for every language that i want for example: prducts_en, products_it where I can store my data with same foreign key to the product but divide from language to make fast query.
Other solution are accepted!!
I never work with large multilanguage database help me and tell me what is the best solution for my database
The first one is the correct solution in general.
It's used in many enterprise applications: a table with an id field for identification of the not multilanguage information (example: unit price for a product) and a table with a row for every combination product/language.
The second one is against every db normalization rule.
The third one is a different derivation of the second one, and if you use an index on the language column in the translated labels table you should not have a great disadvantage in terms of performance.
If you need I will explain better!

database table design for some unknown data

So, not having come from a database design background, I've been tasked with designing a web app where the end user will be entering products, and specs for their products. Normally I think I would just create rows for each of the types of spec that they would be entering. Instead, they have a variety of products that don't share the same spec types, so my question is, what's the most efficient and future-proof way to organize this data? I was leaning towards pushing a serialized object into a generic "data" row, but then are you able to do full-text searches on this data? Any other avenues to explore?
split products and specifications into two tables like this:
products
id name
specifications
id name value product_id
get all the specifations of a product when you know the product id:
SELECT name,
value
FROM specifications
WHERE product_id = ?;
add a specification to a product when you know the product id, the specification's name and the value of said specification:
INSERT INTO specifications(
name,
value,
product_id
) VALUES(
?,
?,
?
);
so before you can add specifications to a product, this product must exist. also, you can't reuse specifications for several products. that would require a somewhat more complex solution :) namely...
three tables this time:
products
id name
specifications
id name value
products_specifications
product_id specification_id
get all the specifations of a product when you know the product id:
SELECT specifications.name,
specifications.value
FROM specifications
JOIN products_specifications
ON products_specifications.specification_id = specifications.id
WHERE products_specifications.product_id = ?;
now, adding a specification becomes a little bit more tricky, cause you have to check if that specification already exists. so this will be a little heavier than the first way of doing this, since there are more queries on the db, and there's more logic in the application.
first, find the id of the specification:
SELECT id
FROM specifications
WHERE name = ?
AND value = ?;
if no id is returned, this means that said specification doesn't exist, so it must be created:
INSERT INTO specifications(
name,
value
) VALUES(
?,
?
);
next, either use the id from the select query, or get the last insert id to find the id of the newly created specification. use that id together with the id of the product that's getting the new specification, and link the two together:
INSERT INTO products_specifications(
product_id,
specification_id
) VALUES(
?,
?
);
however, this means that you have to create one row for every specific specification. e.g. if you have size for shoes, there would be one row for every known shoe size
specifications
id name value
1 size 7
2 size 7½
3 size 8
and so on. i think this should be enough though.
You could take a look at using an EAV model.
I've never built a products database, but I can point you to a data model for that. It's one of over 200 models available for the taking, at Database Answers. Here is the model
If you don't like this one, you can find 15 different data models for Product oriented databases. Click on "Data Models" to get a list and scroll down to "Products".
You should pick up some good design ideas there.
This is a pretty common problem - and there are different solutions for different scenarios.
If the different types of product and their attributes are fixed and known at development time, you could look at the description in Craig Larman's book (http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_1_1/002-2801511-2159202?ie=UTF8&s=books&qid=1194351090&sr=1-1) - there's a section on object-relational mapping and how to handle inheritance.
This boils down to "put all the possible columns into one table", "create one table for each sub class" or "put all base class items into a common table, and put sub class data into their own tables".
This is by far the most natural way of working with a relational database - it allows you to create reports, use off-the-shelf tools for object relational mapping if that takes your fancy, and you can use standard concepts such as "not null", indexing etc.
Of course, if you don't know the data attributes at development time, you have to create a flexible database schema.
I've seen 3 general approaches.
The first is the one described by davogotland. I built a solution on similar lines for an ecommerce store; it worked great, and allowed us to be very flexible about the product database. It performed very well, even with half a million products.
Major drawbacks were creating retrieval queries - e.g. "find all products with a price under x, in category y, whose manufacturer is z". It was also tricky bringing in new developers - they had a fairly steep learning curve.
It also forced us to push a lot of relational concepts into the application layer. For instance, it was hard to create foreign keys to other tables (e.g. "manufacturer") and enforce them using standard SQL functionality.
The second approach I've seen is the one you mention - storing the variable data in some kind of serialized format. This is a pain when querying, and suffers from the same drawbacks with the relational model. Overall, I'd only want to use serialization for data you don't have to be able to query or reason about.
The final solution I've seen is to accept that the addition of new product types will always require some level of development effort - you have to build the UI, if nothing else. I've seen applications which use a scaffolding style approach to automatically generate the underlying database structures when a new product type is created.
This is a fairly major undertaking - only really suitable for major projects, though the use of ORM tools often helps.

Categories