Access to add and change pages is restricted. See: https://cwiki.apache.org/confluence/display/OFBIZ/Wiki+access

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

Introduction

OFBiz is used all over the world by companies doing business in their own country or internationally. This has been recognised early on in the project as being key to the adoption of the project and its works, and to have an internationally diverse community.

Though the default language for code, titles and other messages, and data is English, translations of these elements are essential and many participants in the project have contributed translations to these elements.

The OFBiz rendering engine ensures internationalisation for:

  • entity data translation
  • service messages translation
  • widget element translation
  • content translation


Generic construct of a translation definition

A translation definition is defined in an xml file and governed by the ofbiz-properties.xsd (see https://ofbiz.apache.org/dtds/ofbiz-properties.xsd" ). Translation definitions are also called OFBiz labels, as they are processed through the UiLabelMap services and functionality.

A translation definition looks like:

<property key="<ElementIdentifier>">
     <value xml:lang="<IETF-LanguageTag>"><TranslatedValue></value>
</property>

whereby:

  1. the <ElementIdentifier> is the identifier of what is to be translated, This element is registered in CamelCase, e.g. ProductOverview
  2. the <IETF-LanguageTag> is the language that the renderer is to use for the proper translation, and is in accordance with the IETF BCP 47 language tag definitions, e.g. en, or en-us
  3. the  <TranslatedValue> shows the value of the <ElementIdentifier> in the defined language (<IETF-LanguageTag>)

An example of this:

<property key="BicycleRack">
     <value xml:lang="en">Bicycle Rack</value>
     <value xml:lang="en-us">Bike Rack</value>
     <value xml:lang="nl">Fietsrek</value>
</property>


Entity data translation

The translation definition for entity data follows the general construct for a translation definition as described in the section above.

Translation definitions for entity data are located in the <Component>EntityLabels.xml file within the 'config' folder of the component related to the entity definitions in the files in the  entitydef folder  in the datamodel component. 

As an example:

The entity Product is defined in the product-entitymodel.xml file. As such the data translations for the Product entity go into the ProductEntityLabels.xml file in the config folder of the product component.

Translation of entity data through the rendering engine is facilitated through property files contained in the config folder of the appropriate component(s), associated with the entity model and data files in the data model component. 

A translation defintion for entity data translation looks like:

<property key="FieldDescription.<EntityName>.<fieldName>">
     <value xml:lang="<IETF-LanguageTag>"><TranslatedValue></value>
</property>

whereby the property key value has the following elements:

  1. the fixed value FieldDescription, followed by
  2. a dot (.), followed by
  3. the name of the entity in camel case as represented above through <EntityName>, followed by
  4. a dot (.), followed by
  5. the name of the field defined within the entity in the entity definitions file as represented above through <fieldName>.

As an example:

the entity ProductStore has a field named storeName. The translation definition for this field would thus be defined as

<property key="FieldDescription.ProductStore.storeNaem">
     <value xml:lang="en">The Bicycle Store</value>
     <value xml:lang="en-us">The Bike Store</value>
</property>

An additional translation definition has been defined for the id field of another entity, that is used through a foreign key relationship.

The definition for this translation definition looks like

<property key="<EnityName>.description.<idFieldNameValue>">
     <value xml:lang="<IETF-LanguageTag>"><TranslatedValue></value>
</property>

whereby the property key value has the following elements:

  1. the name of the entity in camel case as represented above through <EntityName>, followed by
  2. a dot (.), followed by
  3. the fixed value description, followed by
  4. a dot (.), followed by
  5. the name of the id field defined within the entity in the entity definitions file as represented above through <idfieldNameValue>.

As an example:

the entity Product has a field named productTypeId, for which a relation is defined to the entity ProductType. The entity ProductType  has a field named description. The translation definition for the productTypeId field in product data records would thus be defined as

<property key="ProductType.description.ASSET_USAGE">
     <value xml:lang="en">Fixed Asset usage</value>
     <value xml:lang="en-us">Equipment Use</value>
</property>

These translations definitions are used in e.g. selection fields (like of the type check, drop-down, radio), where - to enhance the user experience - rather a descriptive field value of a data record is shown than the id value of that record. E.g.

<ProductType productTypeId="1001" description="Fixed Asset Usage"/>


Service message translation

Service messages, such as error or success messages and others,  are generated by functions (in Groovy, Java, Javascript and xml files). These messages are typically shown in log files and through the render engine on screens to the user.

A translation definitions for service messages follows the general construct for a translation definition as described in the section above.

Translation definitions for service messages are located in the <Component>ServiceLabels.xml file within the 'config' folder of the component where the groovy, java, javascript or xml function is initially defined.

As an example:

When the a function in categories services returns 0 products that meet the defined select criteria the function could call the translation for message 'categoryservices.product_not_found'. The translation definition would then be:

<property key="categoryservices.ProductNotFound">
     <value xml:lang="en">Product not found</value>
     <value xml:lang="en-us">Product data is not available</value>
     <value xml:lang="nl">Product niet gevonden</value>
</property>

As the function for this categoryservices function is to be included in the product component (due to the aspect that category as entity is defined in the product-entitymodel.xml file), the translation definition for categoryservices.ProductNotFound is to be included in ProductServiceLabels.xml in the config folder of the product component.

Current situation (per ultimo 2021)

Currently, service message translations are incorporated in:

  • <Component>ErrorLabels.xml
  • <Component>UiLabels.xml


Widget Element Translation

A translation definition can be applied to particular widget definitions, like screen titles, form, grid, field labels, screenlet titles, container and  label text, etc. These translation definitions can be applied within both widget definitions in xml files and in Freemarker template (.ftl) files for forms, grids and fields

The translation definition for a widget element follows the general construct for a translation definition as described in the section above.

Translation definitions for a widget element translations are located in the <Component>UiLabel.xml file within the 'config' folder of the component where the translation is initially to be applied (can be business domain specific, eg com related translations in the marketing component).

Widget Element Translations are handled by the render engine through the incorporation of following construct in a widget:

element="${uiLabelMap.<propertyKeyValue>}"

whereby the construct has the following elements:

  1. element is the attribute (according to ofbiz xsd file) that is defined to work with translations
  2. uiLabelMap is the fixed element used by the render engine to apply its translation function, followed by
  3. a dot (.), followed by
  4. the name of translation definition as represented above through <propertyKeyValue>.

An example:

Pretend there is a need to show in a screen widget in the accounting application a label widget having text "Welcome to the main page of this application". This label widget would then be:

<label text="${uiLabelMap.WelcomeMessage}"/>

The translation for this label test would then be:

<property key="WelcomeMessage">
     <value xml:lang="en">Welcome to the main page of this application</value>
     <value xml:lang="en-us">Welcome here</value>
</property>

Component specific vs generic translation definitions

Translation definitions for widget elements are commonly domain specific, e.g. applicable to accounting, warehousing, sales, etc. 
In OFBiz these elements and thus their translation definitions are grouped through components and their applications, like the domains of PIM and WHM in the product component, and accounting and budgeting in the accounting component. 

Generic translation definitions, however, are not included in the domain oriented <component>UiLabels.xml files, but rather in the CommonUiLabels.xml file in the config folder of the common component in the framework stack


Field widget title translation

Field widget title translations (aka FormFieldTitle label) are a special case of widget translation definitions as they are related to both related to data records (based on field definitions in entity definitions, included in the <component-entitymodel.xml file in the datamodel component) and a widget element definition as defined in a <DomainOriented>Forms.xml file in the widgets folder in a component, eg PaymentManagementScreens.xml in the accounting component.

Given the conundrum above, Field widget title translation definitions are located in the <Component>UiLabel.xml file in the config folder of the component that is associatied with the entity definition.

For a field widget title translation the following options available are:

  1. the default FormFieldTitle translation definition, or
  2. application of another widget translation definition

The FormFieldTitle translation definition, follows the general construct for a translation definition as described in the section above, and is done as follows:

A translation defintion for a field widget title translation looks like:

<property key="FormFieldTitle_<fieldWidgetName>">
     <value xml:lang="<IETF-LanguageTag>"><TranslatedValue></value>
</property>

whereby the property key value has the following elements:

  1. the fixed value FormFieldTitle, followed by
  2. an underscore (_), followed by
  3. the name of the field widget within the form or grid widget as represented above through <fieldWidgetName>.

As an example:

.<property key="FormFieldTitle.productId">
     <value xml:lang="en">Product Id</value>
     <value xml:lang="en-us">Product ID</value>
</property>

As an example, for a product record (as defined as an the Product entity in the product-entitymodel.xml file) to be rendered as a web page, following form widget:

<form name="Product", default-entity-map="Product" list="productDetails">
<auto-fields-entity entity-name="Product" default-field-type="display/>
<field name="productId><display/><field>
<field name="internalName" title="${uiLabelMap.ProductName}
<field name="product" title="${uiLabelMap.Retrieved} ${uiLabelMap.Product}">
<display-entity entity-name="Product key-field-name="productId" description="${productId} - ${internalName}"/>
</field>
</form>

illustrates the various options available for field label rendering and application of label translations.

For field label rendering the engine now performs multiple functions:

  1. for the field widget definition without a title element (as in '<field name="productId"><display/></field>)

    1. the render looks if a default translation definition is available for the field widget (aka the FormFieldTitle translation definition), and if none is available
    2. show the name of the  field widget ("productId") as a label in spaced camel case, meaning 'Product Id"
  2. for the field widget with a defined title
    1. (as in <field name="internalName" title="${uilLabelMap.ProductName}"><display"/></field>}, show the translation for the given translation definition (<property key="ProductName"> ..</property>)
    2. (as in <field name="product" title="${uiLabelMap.Retrieved} ${uiLabelMap.Product}"><display-entity .../><field>, the translations for each of the given translation definitions (<property key=Retrieved"> ..</property> and <property key="Product"> ..</property>)


Content Translation

Translations fo data records as generated through the content component and application is available for specific elements in other components and entities therefrom, e.g. through the association of a content object with a product object, a locale specific content object can be rendered.


How-to ensure localisation is applied to widget elements

Ensuring that the correct translation is applied by the widget engine given the user's locale is achieved through the inclusion of a property-map element in the <actions>..</actions> in a section widget of a screen widget.

As an example:

<screen name="main-decorator>
<section>
<actions>
<property-map resource="ProductUiLabels" map-name="uiLabelMap" global="true"/>
</actions>
</section>
...
</screen>

This examples shows:

  1. the referenced <component>UiLabels.xml file ( "ProductUiLabels", giving ProductUiLabels.xml) in the config folder of the product component
  2. the map-name, as required by the translation functions in the rendering engine and used in the various widget elements (map-name="uiLabelMap")

Best practice(s) regarding translations

First and foremost, apply common sense when considering to contribute a translation definition to the project. Translation definitions and the applications thereof in OFBiz are intended to:

increase the appeal of OFBiz for all kinds (potential) users, whether they be companies implementing it as its prime solution or the persons in those companies having to work with it

Translation definitions need to be maintained, like the rest of the OFBiz code. And this is done by volunteers (like you) with time constraints. Adding a translation definition without an explanation where (in which service, or which widget element) it is – to be - used, is most likely not to be accepted by the community.

Also, consider whether the widget element, in the specific component where you want to have the translation definition applied, can do with a translation definition from another component or not.

Too many translation definitions for in essence the same thing, creates confusion among the contributors about what to apply where and when leading to undesired heated right-wrong debates.

in the various forms and grid widgets across several components and their applications, we apply the field widget for the productId (<field name="productId"..><..> to

  1. either associate a particular product with the entity record that is being edited (through the LookupProduct functionality)
  2. either reference a particular product by showing a retrieved product Id value, a retrieved internal name value, another value from the product record, or a combination of the values of multiple field values of the product record

For this the usability of the users we currently have following translation definitions as options:

CONTEXTLABELCOMPONENTTRANSLATIONSNecessary in field widget?
PRODUCTproperty key="AccountingProductId">ACCOUNTING17No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="FormFieldTitle_productId">ACCOUNTING17No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="ManufacturingProductId">MANUFACTURING13No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="PartyProductId">PARTY17No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="FormFieldTitle_productId">PRODUCT14No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="ProductProductId">PRODUCT13No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="WorkEffortProductId">WORKEFFORT13No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="FormFieldTitle_productId">WORKEFFORT13No, use property key="FormFieldTitle_productId"> from the product component
PRODUCTproperty key="ProductProduct">PRODUCT14Yes, when a number of field values of a product record are combined to be displayed in a field widget. e.g. <display description="${product.productId) - ${product.internalName}"/>

Be smart by applying common sense over dogma.

As an example: https://localhost:8443/partymgr/control/PartyFinancialHistory?partyId=EuroCustomer

In this example in the Party component there is a screen widget that shows a financial overview of invoices and payments for a given party. This screen widget uses a form widget 'PartyFinancialSummary' which displays record data in a grid

The first overview in that screen shows invoice details  (invoice id, type, date and total amount due) left of the column with title 'Outstanding amount" and right of the column with 'Amount Applied' details of an associated payment (payment Id, payment date, payment amount):

[demo11001]Sales Invoice4/25/06$820.28$0.00$820.28[demo10001]4/25/06$820.97


When considering applying (and/or defining translation definitions) for such a screen in the party component, consider whether:

  • In the column showing the invoice Id, it would be necessary to have a transition definition for field widget '<field name="invoiceId"...><display/><field> and thus have OFBiz render the default for the field widget (aka the FormFieldTitle label, or rather apply a generic translation definition (associated with the entity associatied: Invoice)
  • in the column showing the type of the invoice, would it be necessary to define and apply a translation definition in the party component for the field widget that applies a data element from an entity definition from the accounting component (the Invoice definition)
  • in the column showing the total value, would it be necessary to define and apply a translation definition in the party component for the field widget when the translation definition is generic and common across multiple OFBiz components and applications. 
  • No labels