A: 

Your Products table is schizophrenic, its entity is sometimes Product and sometimes Variant. This leads to very cumbersome behavior. For example, you'd like the question "how many different products do we have?" be answered by select count(*) from products, but here this gives the wrong answer, to get the correct answer you have to know the Magic Number 0 and query select count (*) from products where master=0. "List all products and how many variants we have for each" is another query that should be straightforward but now isn't. There are other anomalies, like the fact that the first line in products_descriptions is a shirt that has a price and a picture but no size (size is stored in the variants, but they have prices and pictures of their own).

Your problem sounds like you have products in two contexts: (1) something that can be displayed as an item in your store, and (2) something that can be ordered by your customer. (1) probably has a name like "Halloween T-Shirt" or so, and it probably has an image that the customer sees. (2) is what the customer orders, so it has a (1), but also a variant specification like "small" or maybe a color "red". It probably has a price, too, and an order_id so your shop can know what specific item to ship.

You should give each context an entity. Here's how i'd do it

displayable_product
id   name
1    "Baseball Cap"
2    "T-Shirt"

orderable_product
id   d_product_id order_id  size    color   price
1    1            123               red      9.99
2    2            456       small           19.99
3    2            789       medium          21.99

displayable_content
id   d_product_id  locale  name                 image
1    1             en_US   "Baseball Cap"       baseballcap.jpg
2    1             es_US   "Gorra de Beisbol"   baseballcap.jpg
3    2             en_US   "Nice T-Shirt"       nicetshirt.jpg
4    2             es_US   "Camiseta"           nicetshirt.jpg

You should probably use locale instead of country in the display tables to account for countries with more than one language (USA, Switzerland, and others), and you might separate the size and color into its own variants table. And if you need country-dependent data on the orderables (like different prices/currencies for shipping to different countries), you'd have to extract a country-dependent orderable_content table, too.

wallenborn
Interesting example. But what do you do if the number of options are unknown? Like "Slewvless"? Should you normalize that?
Cudos
I would try to keep the database normalized as long as possible. In your case, i'd try to sort the options into two buckets: (1) those that are structural in the sense that they may end up in queries like "this year, how many customers preferred red if red, white and blue are offered", and (2) those that resemble describing text more than categories. Ideally, bucket (2) would be empty, but in real life, i can be larger than (1). But basically, if something shows up in queries often, i want it normalized. If it's used only in descriptions, then putting it into an EAV table is ok.
wallenborn