6

データベースを使用してi18nキーと値のペアを保存し、実行時にi18nデータを変更/再読み込みできるようにしたいと思います。誰かがこれをしましたか?または、これを実装する方法について誰かが考えていますか?私はこれについていくつかのスレッドを読みましたが、実行可能な解決策を見ていません。

具体的には、次のようなjstlタグで機能するものを指します。

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

これにはResourceBundleの拡張が含まれると思いますが、これを試したときに、jstlタグがリソースバンドルを取得する方法に関係する問題が発生しました。

4

4 に答える 4

13

上記のdanbの助けを借りて、ようやくこれが機能するようになりました。

これは私のリソース バンドル クラスとリソース バンドル コントロール クラスです。

@[danb] のこのコードを使用しました。

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));

そしてこのクラスを書きました。

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;
            }

        };
    }
于 2008-08-28T13:49:04.837 に答える
2

DBにUTF-8/16文字を格納する方法を尋ねているだけですか?mysqlでは、UTF8サポートを使用してビルドし、それをデフォルトとして設定するか、列またはテーブルレベルで指定するだけです。私は以前にoracleとmysqlでこれを実行しました。テーブルを作成し、i18nデータをカットアンドペーストして、何が起こるかを確認します...すでに設定されている可能性があります。

または私はあなたのポイントを完全に逃していますか?

編集:

より明確にするために...私は通常3列のテーブルを実装します...言語、キー、値...ここで「値」には潜在的に外国語の単語またはフレーズが含まれます...「言語」にはいくつかの言語キーと「キー」が含まれますは英語のキー(つまりlogin.error.password.dup)です...言語とキーはインデックス付けされています...

次に、このような構造にインターフェースを構築し、各キーとそのすべての翻訳(値)を表示します...それは派手になり、監査証跡や「ダーティ」マーカー、および翻訳者とデータを有効にするために必要な他のすべてのものを含めることができますそれを利用するためのエントリーフォーク..

編集2:

JSTLタグに関する情報を追加したので、もう少し理解できます...自分でそれを行ったことはありません..しかし、サーバー側でこの古い情報を見つけまし...

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));
于 2008-08-21T03:48:51.590 に答える
1

キー/言語/用語を含むデータベーステーブルがあります。ここで、キーは整数であり、言語と組み合わせた主キーです。

Strutsを使用しているため、のようなことを実行できる独自のPropertyMessageResources実装を作成することになりまし<bean:message key="impressum.text" />た。

これは非常にうまく機能し、フロントエンドで言語を動的に切り替えたり、その場で翻訳を更新したりする柔軟性を提供します。

于 2008-08-21T05:36:50.990 に答える
0

実際、ScArcher2 が必要としたのは、正しいまたは役立つとマークされていないデビッドの応答です。

ScArcher2 が使用することを選択した解決策は、ひどいメサケです:) 一度にすべての翻訳をロードする...どんな大きなアプリケーションでも、それはそれを殺します. リクエストごとに何千もの翻訳を読み込んでいます...

デビッドの方法は、実際の運用環境でより一般的に使用されています。場合によっては、すべてのメッセージが翻訳される際に db 呼び出しを制限するために、トピック、機能などごとに翻訳のグループを作成して、それらをプリロードすることができます。しかし、これはもう少し複雑で、優れたキャッシュ システムで置き換えることができます。

于 2012-08-31T07:34:45.973 に答える