قاعدة البيانات المدعومة i18n لتطبيق جافا على الويب

StackOverflow https://stackoverflow.com/questions/19295

  •  09-06-2019
  •  | 
  •  

سؤال

أرغب في استخدام قاعدة بيانات لتخزين أزواج مفاتيح/قيمة i18n حتى نتمكن من تعديل/إعادة تحميل بيانات i18n في وقت التشغيل.وقد فعل أي شخص هذا؟أو هل لدى أي شخص فكرة عن كيفية تنفيذ ذلك؟لقد قرأت عدة مواضيع حول هذا الأمر، ولكن لم أجد حلاً عملياً.

أنا أشير على وجه التحديد إلى شيء من شأنه أن يعمل مع علامات jstl مثل

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

أعتقد أن هذا سيتضمن توسيع ResourceBundle، ولكن عندما حاولت ذلك واجهت مشكلات تتعلق بالطريقة التي تحصل بها علامات jstl على حزمة الموارد.

هل كانت مفيدة؟

المحلول

هل تسأل فقط عن كيفية تخزين أحرف UTF-8/16 في قاعدة البيانات؟في mysql، الأمر يتعلق فقط بالتأكد من أنك تقوم بالإنشاء بدعم UTF8 وتعيينه كافتراضي، أو تحديده على مستوى العمود أو الجدول.لقد قمت بذلك في Oracle و MySQL من قبل.أنشئ جدولاً وقم بقص بعض بيانات i18n ولصقها فيه وشاهد ما يحدث...ربما تم ضبطك بالفعل..

أم أنني أفتقد وجهة نظرك تمامًا؟

يحرر:

لنكون أكثر وضوحا..عادةً ما أقوم بتنفيذ جدول مكون من ثلاثة أعمدة ...اللغة، المفتاح، القيمة...حيث تحتوي "القيمة" على كلمات أو عبارات لغة أجنبية محتملة...تحتوي "اللغة" على بعض مفاتيح اللغة و"المفتاح" هو مفتاح باللغة الإنجليزية (أي.تسجيل الدخول.خطأ.كلمة المرور.dup)...تتم فهرسة اللغة والمفتاح...

لقد قمت بعد ذلك ببناء واجهات على هيكل مثل هذا يظهر كل مفتاح بكل ترجماته (قيمه)...يمكن أن يكون رائعًا ويتضمن مسارات التدقيق والعلامات "القذرة" وجميع الأشياء الأخرى التي تحتاجها لتمكين المترجمين ومدخلي البيانات من الاستفادة منها.

تحرير 2:

الآن بعد أن أضفت المعلومات حول علامات JSTL، فهمت المزيد قليلاً...لم أفعل ذلك بنفسي قط..ولكن وجدت هذه المعلومات القديمة على com.theserverside...

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

نصائح أخرى

أخيرًا حصلت على هذا العمل بمساعدة danb أعلاه.

هذه هي فئة حزمة الموارد الخاصة بي وفئة التحكم في حزمة الموارد.

لقد استخدمت هذا الرمز من @[danb]'s.

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

        };
    }

لدينا جدول قاعدة بيانات يحتوي على مفتاح/لغة/مصطلح حيث المفتاح هو عدد صحيح n وهو مفتاح أساسي مدمج مع اللغة.

نحن نستخدم Struts، لذلك انتهى بنا الأمر إلى كتابة ما لدينا PropertyMessageResources التنفيذ الذي يسمح لنا أن نفعل شيئا من هذا القبيل <bean:message key="impressum.text" />.

إنه يعمل بشكل جيد للغاية ويمنحنا المرونة اللازمة لتبديل اللغات ديناميكيًا في الواجهة الأمامية بالإضافة إلى تحديث الترجمات بسرعة.

في الواقع ما يحتاجه ScArcher2 هو استجابة ديفيد التي لم يتم وضع علامة عليها على أنها صحيحة أو مفيدة.

الحل الذي اختار ScArcher2 استخدامه هو خطأ فادح من imo :) تحميل جميع الترجمات في وقت واحد...في أي تطبيق أكبر سوف يقتله.جارٍ تحميل آلاف الترجمات لكل طلب...

تُستخدم طريقة ديفيد بشكل أكثر شيوعًا في بيئات الإنتاج الحقيقية.في بعض الأحيان، للحد من مكالمات قاعدة البيانات، والتي تتم مع كل رسالة مترجمة، يمكنك إنشاء مجموعات من الترجمات حسب الموضوع والوظيفة وما إلى ذلك.لتحميلها مسبقًا.لكن هذا أكثر تعقيدًا بعض الشيء ويمكن استبداله بنظام ذاكرة تخزين مؤقت جيد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top