Just a little background. . .

Broadleaf Commerce is an enterprise class, open source eCommerce framework currently available on GitHub here. It's built in Java on top of frameworks such as Spring and Hibernate, among others. So if you haven't checked it out, I highly recommend downloading the Maven archetype (ecommerce-archetype) and getting the demo application up and running. The tutorial outlined below assumes that you already have a basic knowledge of how Broadleaf works and that you understand the basics of product extensions.

As of Broadleaf 1.52M2 release

there is no support for product internationalization as of yet. It is definitely on the road map and coming soon. You can also check out what else is on the horizon here. If however you find yourself needing to internationalize your product catalog right away (as in my case), here's one way of accomplishing it:

All I really needed to internationalize was the name and description of the product, so for the purposes of this article, that's what I'll be going over in detail. You can however take the same principles outlined here to internationalize the rest of your application if you so desire.

Step 1: Extend the Broadleaf Product
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@Table(name="RUNNING_GEAR_PRODUCT")
public class RunningGearProductImpl extends ProductSkuImpl implements RunningGearProduct {

@Column(name = "RG_SPECIAL_ATTRIBUTE")
private String rgSpecialAttribute;
Step 2: Did you know that the 18 in i18n is for the 18 characters between the first and last letters of. . .

Internationalization is such a long word to type. . . Great! We've got our store up and running and our sales are booming in the US. Let's expand! To do that, we can create this localization class, let's call it i18NProductInfo. Like so:

@Entity
@Table(name = "RUNNING_GEAR_I18N_PRODUCT_INFO")
public class I18NProductInfo implements Serializable {

    @Id
    @GeneratedValue(generator = "rgI18nProductInfoId", strategy = GenerationType.TABLE)
    @TableGenerator(name = "rgI18nProductInfoId", table = "SEQUENCE_GENERATOR", pkColumnName = "ID_NAME", valueColumnName = "ID_VAL", pkColumnValue = "i18nProductInfo", allocationSize = 50)
    @Column(name = "PRODUCT_INFO_ID")
    @AdminPresentation(friendlyName = "i18n Product Info ID", group = "Primary Key", hidden = true)
    private Long id;

    @Column(name = "LANGUAGE_KEY", length = 2)
    private String language;
    @Column(name = "PRODUCT_NAME")
    private String name;

    @Column(name = "PRODUCT_DESC")
    private String description;

    @ManyToOne
    private RunningGearProductImpl product;
}

So if you notice here, we've created a @ManyToOne mapping with RunningGearProductImpl. Let's go ahead and add a complimentary mapping to our product as well. Like this:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "RUNNING_GEAR_PRODUCT")
public class RunningGearProductImpl extends ProductSkuImpl implements RunningGearProduct {

    @Column(name = "RG_SPECIAL_ATTRIBUTE")
    private String rgSpecialAttribute;

    @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinColumn(name = "PRODUCT_ID")
    @MapKeyColumn(name = "LANGUAGE_KEY")
    private Map i18nProductInfo;

}

Now that we have a language map on our domain object, we can easily access the different languages on our JSP using JSTL by doing something like this:

${runningGearProduct.i18nProductInfo[languagePref].name}

In the above example, "languagePref" is an attribute we set on our model in the controller. The map would look something like this: {en="This is a product description", fr="Il s'agit d'une description du produit", sp="Esta es una descripciĆ³n del producto"} You can also override the CustomerStateFilter and set the language on the customer or put it in session if you wish. There are plenty of options, and I'll leave it up to you to decide what works best for you.

So, this is just one way of quickly internationalizing your product catalog using Broadleaf Commerce. Hopefully this gives you a clean flexible solution to add multiple languages to your site.