Veri tabanı i18n java web uygulaması için


6

i18n anahtar/değer çiftlerini saklamak için bir veritabanı kullanmak istiyorum, böylece çalışma zamanında i18n verilerini değiştirebilir/yeniden yükleyebiliriz. Bunu yapan var mı? Yoksa bunun nasıl uygulanacağı konusunda bir fikri var mı? Bununla ilgili birkaç konu okudum ama işe yaramaz bir çözüm görmedim.

özellikle ben bu ResourceBundle uzanan içerecektir düşünüyorum böyle

<fmt:setlocale> 
<fmt:bundle> 
<fmt:setBundle> 
<fmt:message> 

olarak JSTL etiketleri ile çalışacak bir şeye atıfta değilim, ama bu çalıştığında ile yapmak zorunda sorunlarla karşılaştı jstl etiketlerinin kaynak paketini alma yolu.

2

Sadece DB'de UTF-8/16 karakterleri nasıl kaydedeceğinizi mi düşünüyorsunuz? mysql'de sadece UTF8 desteğiyle oluşturduğunuzdan ve varsayılan olarak ayarlayarak veya sütun veya tablo düzeyinde belirttiğinizden emin olmanız önemlidir. Bunu daha önce oracle ve mysql'de yaptım. Bir tablo oluşturun ve kimi i18n verilerini kesip yapıştırın ve ne olduğunu görün ... zaten ayarlanmış olabilirsiniz ..

Yoksa tamamen noktanızı mı kaçırdım?

düzenleme:

daha açık olmak gerekirse ... Ben genellikle "değer" potansiyel yabancı dil kelime veya kelime grubu içeren bir üç sütun tablo ... dil, anahtar, değer ... uygulamak ... " dil "bazı dil anahtarını içerir ve" anahtar "bir ingilizce anahtardır (örn. login.error.password.dup) ... dil ve anahtar dizinlenir ...

Daha sonra böyle bir yapı üzerinde arabirimler oluşturdum Bu, tüm çevirileri (değerleri) ile her anahtarı gösterir ... Bu fantezi ve kontrol yollar ve "kirli" belirteçleri ve çevirmenler ve veri girişi folk etkinleştirmek için gereken diğer tüm diğer şeyler de içerebilir ..

Düzenleme 2: JSTL etiketleri hakkında bilgi eklediği Şimdi

, ben kendimi .. ama ...

theserverside bu eski bilgi bulduğunu hiç yapmadım ... biraz daha iyi anlamak
HttpSession session = .. [get hold of the session] 
ResourceBundle bundle = new PropertyResourceBundle(toInputStream(myOwnProperties)) [toInputStream just stores the properties into an inputstream] 
Locale locale = .. [get hold of the locale] 
javax.servlet.jsp.jstl.core.Config.set(session, Config.FMT_LOCALIZATION_CONTEXT, new LocalizationContext(bundle ,locale)); 

1

Anahtarın tamsayı olduğu ve dil ile birlikte birleştirilmiş birincil anahtar olduğu anahtar/dil/terime sahip bir veritabanı tablomuz var. Biz Struts kullanan

, böylece kendi PropertyMessageResources bize <bean:message key="impressum.text" /> böyle bir şey yapmak için izin verir uygulanmasını yazma sona erdi.

Çok iyi çalışıyor ve bize ön uçtaki dilleri dinamik olarak değiştirme ve çevirileri anında güncelleştirme konusunda esneklik sağlıyor.


13

Nihayet bu çalışmanın danb'nin yardımı ile çalıştım.

Bu, kaynak grup sınıfım ve kaynak paket denetimi sınıfım.

Bu kodu @ [danb] 'dan kullandım.

ResourceBundle bundle = ResourceBundle.getBundle("AwesomeBundle", locale, DbResourceBundle.getMyControl()); 
javax.servlet.jsp.jstl.core.Config.set(actionBeanContext.getRequest(), Config.FMT_LOCALIZATION_CONTEXT, new LocalizationContext(bundle, locale)); 

ve bu sınıfı yazdı.

public class DbResourceBundle extends ResourceBundle 
{ 
    private Properties properties; 

    public DbResourceBundle(Properties inProperties) 
    { 
     properties = inProperties; 
    } 

    @Override 
    @SuppressWarnings(value = { "unchecked" }) 
    public Enumeration<String> getKeys() 
    { 
     return properties != null ? ((Enumeration<String>) properties.propertyNames()) : null; 
    } 

    @Override 
    protected Object handleGetObject(String key) 
    { 
     return properties.getProperty(key); 
    } 

    public static ResourceBundle.Control getMyControl() 
    { 
     return new ResourceBundle.Control() 
     { 

      @Override 
      public List<String> getFormats(String baseName) 
      { 
       if (baseName == null) 
       { 
        throw new NullPointerException(); 
       } 
       return Arrays.asList("db"); 
      } 

      @Override 
      public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, 
        InstantiationException, IOException 
      { 
       if ((baseName == null) || (locale == null) || (format == null) || (loader == null)) 
        throw new NullPointerException(); 
       ResourceBundle bundle = null; 
       if (format.equals("db")) 
       { 
        Properties p = new Properties(); 
        DataSource ds = (DataSource) ContextFactory.getApplicationContext().getBean("clinicalDataSource"); 
        Connection con = null; 
        Statement s = null; 
        ResultSet rs = null; 
        try 
        { 
         con = ds.getConnection(); 
         StringBuilder query = new StringBuilder(); 
         query.append("select label, value from i18n where bundle='" + StringEscapeUtils.escapeSql(baseName) + "' "); 

         if (locale != null) 
         { 
          if (StringUtils.isNotBlank(locale.getCountry())) 
          { 
           query.append("and country='" + escapeSql(locale.getCountry()) + "' "); 

          } 
          if (StringUtils.isNotBlank(locale.getLanguage())) 
          { 
           query.append("and language='" + escapeSql(locale.getLanguage()) + "' "); 

          } 
          if (StringUtils.isNotBlank(locale.getVariant())) 
          { 
           query.append("and variant='" + escapeSql(locale.getVariant()) + "' "); 

          } 
         } 
         s = con.createStatement(); 
         rs = s.executeQuery(query.toString()); 
         while (rs.next()) 
         { 
          p.setProperty(rs.getString(1), rs.getString(2)); 
         } 
        } 
        catch (Exception e) 
        { 
         e.printStackTrace(); 
         throw new RuntimeException("Can not build properties: " + e); 
        } 
        finally 
        { 
         DbUtils.closeQuietly(con, s, rs); 
        } 
        bundle = new DbResourceBundle(p); 
       } 
       return bundle; 
      } 

      @Override 
      public long getTimeToLive(String baseName, Locale locale) 
      { 
       return 1000 * 60 * 30; 
      } 

      @Override 
      public boolean needsReload(String baseName, Locale locale, String format, ClassLoader loader, ResourceBundle bundle, long loadTime) 
      { 
       return true; 
      } 

     }; 
    } 

0

Doğru olarak ScArcher2'nin gereksinim duyduğu şey, doğru ya da yardımcı olarak işaretlenmemiş olan david yanıtıdır.

ScArcher2 çözümü kullanmayı tercih etti imo korkunç mestake :) Bir kerede tüm çevirileri yükleme ... daha büyük bir uygulamada onu öldürür. Her isteğin tercümelerinin yüklenmesi ...

david'in yöntemi, gerçek üretim ortamlarında daha yaygın olarak kullanılmaktadır. Bazen, çevrilen her iletiyle gelen db çağrılarını sınırlamak için, bunları önceden yüklemek için konuya, işlevsellik vb. Göre çeviri grupları oluşturabilirsiniz. Ama bu biraz daha karmaşık ve iyi önbellek sistemi ile ikame edilebilir.

  0

Tüm çevirileri daha büyük uygulamalara yüklemenin sorunlara neden olabileceğini kabul ediyorum. Bizim durumumuzda bu bir sorun değildi ve bizim ihtiyacımızı karşıladı. Kodum, herhangi bir zamanda yalnızca çevirilerin bir alt kümesini saklayan bir önbellek mekanizması kullanmak için değiştirilebilir. Kod, tüm durumlarda en iyi olanın değil, çalışılan şeyin bir örneğiydi. 05 eyl. 122012-09-05 15:01:31