-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Internationalization example
PostPosted: Thu May 04, 2006 5:45 am 
Newbie

Joined: Fri Jul 30, 2004 12:06 pm
Posts: 5
Location: Madrid
Hi all!

I have a running application developed with Hibernate (and Struts and Spring and...) and now I have to face the internationalization of some lookup tables we're using to populate combos. The content of these tables can be updated by users and in the new internationalized scenario this requirement does not dissapear.

I've been reading Gavin King's article in The Server Side regarding the internationalization using UserType but I don't fully understand how to do this.

My current db schema is like follows:

LOOKUP_TABLE_A
---------------------
id : PK (assigned by sequence)
name
description

LOOKUP_TABLE_B
---------------------
id: PK (assigned by sequence)
name
description
idA: FK to LOOKUPTABLE_A

BUSINESS_TABLE_1
-----------------------
id: PK (assigned by sequence)
fieldA
fieldB
...
idB: FK to LOOKUP_TABLE_A


My POJOs are like follows:
Business1 {
id : Long
fieldA
fieldB
...
objectB : LookupB
}
LookupB {
id : Long
name : String
descr : String
objectA : LookupA
}
LookupA {
id : Long
name : String
descr : String
}

Which are the changes you suggest to my application in order to minimize the impact in the code that is already running.

Thanks a lot in advance,
Jose M Beas


Hibernate version: 3.0


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 05, 2006 12:42 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Are you ok with seeing the non-internationalized version when you look up the DB directly? If you are, then the standard way of doing this would be to use the contents of the field that you want to internationalize as a property in a properties bundle, then just use java's internationalization facilities (see java.util.ResourceBundle's javadocs as a starting point). This would happen at the UI layer, so nothing lower than that would change at all.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 05, 2006 3:14 am 
Newbie

Joined: Fri Jul 30, 2004 12:06 pm
Posts: 5
Location: Madrid
tenwit wrote:
Are you ok with seeing the non-internationalized version when you look up the DB directly?


Dear tenwit,

I'm afraid I'm not sure what you meant with "seeing". If you meant "not updating", I'm afraid I'm not ok. I mean, I NEED (it's a requirement) to be able to update these values (that's why originally they are in the database).

Thanks,
Jose M Beas


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 05, 2006 5:34 am 
Newbie

Joined: Fri Jul 30, 2004 12:06 pm
Posts: 5
Location: Madrid
Hi again!

I'm working on a sample like follows:

Code:
create table RIESGO_PAIS (
   ID bigint not null,
   primary key (ID)
);
create table RIESGO_PAIS_I18N (
   ID bigint not null,
   LOCALE char(2) not null,
   NOMBRE varchar(30),
   primary key (ID,LOCALE)
);
alter table RIESGO_PAIS_I18N
   add constraint RIESGO_PAIS_I18N_ID
   foreign key (ID)
   references RIESGO_PAIS
;
create table dual_RIESGO_PAIS ( zero integer );
insert into dual_RIESGO_PAIS values (0);
create sequence SEQ_RIESGO_PAIS start with 100;
insert into RIESGO_PAIS values (0);
insert into RIESGO_PAIS values (1);
insert into RIESGO_PAIS_I18N values (0,'ES','Bajo');
insert into RIESGO_PAIS_I18N values (1,'ES','Alto');
insert into RIESGO_PAIS_I18N values (0,'EN','Low');
insert into RIESGO_PAIS_I18N values (1,'EN','High');
insert into RIESGO_PAIS_I18N values (0,'PT','Baixo');
insert into RIESGO_PAIS_I18N values (1,'PT','Alto');


That's my hsqldb script.

I wanted to have a POJO like follows:

Code:
/**
*        @hibernate.class
*         table="RIESGO_PAIS"
*/
public class RiesgoPais implements Serializable {
   
   private Long id;

   /**
     *            @hibernate.id
     *             generator-class="sequence"
     *             column="ID"
     *             type="java.lang.Long"
     *            @hibernate.generator-param
     *              name="sequence"
     *              value="SEQ_RIESGO_PAIS"
     */
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
                }
         
   private String locale;
   private String nombre;
   
   // ...and the corresponding getters/setters
         
}


I want my DAO to have the following method:

Code:
List getAll(String locale);


and to be able to pass this test (using the former testing database):

Code:
   public void testListado_i18n() throws Exception {
      List resultado = riesgoPaisDAO.getAll("EN");
      assertEquals(2,resultado.size());
   }


Now I'm stalled because I haven't got any success neither using UserType nor <map>. With <map> I had some success, but not complete.
Does anyone have ANY idea? Of course I'm open to change ANYTHING (including the database schema).

Thanks in advance,
Jose Manuel Beas


Top
 Profile  
 
 Post subject:
PostPosted: Sun May 07, 2006 6:20 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
What I meant was, do you have to see the Spanish, Portugese and English words in the database itself? Because the usual solution to this is to have a lookup value in the databse, and language files in your application(s) that map that key to readable text in the appropriate language.

Assuming that this isn't possible for you, then my recommendation would be to do the "usual solution", except entirely in the DB. That is, have every string that needs to be internationalized be in one table, then have every table that needs an internationalized string have a key into that table. This allows you to implement your suggested solution, or to skip the join to the internationalization table and do it in java, as per my suggested solution. The only downside to this solution is that you'll need a language parameter to every join to the internationalization table, or else you'll get multiple rows. This can be mitigate by choosing "sensible" strings as your internationalization string.

To work with your example, you'd replace RIESGO_PAIS_I18N with a I18N_STRINGS table, and use a string key like "baja", "alto" etc. Then in the I18N_STRINGS table, you'd have a composite key, being that string key, and the country code or key. Then any table that needed to record a country's risk would record that key: it would up to the application or query to add in the country code/key, so that the query could be made specific enough to return a single row.

As I said before, this last step (the resolution of the string key) is normally done in java, using the ResourceBundle class.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 08, 2006 4:11 am 
Newbie

Joined: Fri Jul 30, 2004 12:06 pm
Posts: 5
Location: Madrid
Dear tenwit,

The original requirement was that users must be able to change the literals for the (i.e.) country risks. Now, in an internationalized scenario, users must be able to change the literals for different languages.

I have found a number of solutions to show the whole information (including literals) for a given language, but I still cannot update or delete accordingly.

Thanks again,
Jose M Beas


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 08, 2006 5:45 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Ah right, that's slightly different from the norm, then. I suppose that the thing to do is to map the literals to a map, keyed by language. If languages are mapped entities, then you can use map-key-many-to-many to use the language objects as keys to the internationalized strings. If your object model includes Country, which has a Risk, which is a map of risk strings indexed by Language, you might have something like:
Code:
<class name="Country" ...>
  ...
  <map name="Risk" ...>
    <key column="CountryID" not-null="true"/>
    <map-key-many-to-many column="LanguageID" class="Language"/>
    <element column="StringI18N" type="string"/>
  </map>
  ...
</class>
I think that this will allow you to do everything you need.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.