2011-06-23 15 views
8

मुझे 2.3 servlet विनिर्देश का उपयोग करके एक जे 2 ईई वेब एप्लिकेशन में i18n पेश करने का (बल्कि चुनौतीपूर्ण) कार्य दिया गया है। आवेदन बहुत बड़ा है और 8 से अधिक वर्षों से सक्रिय विकास में रहा है।जावा वेब एप्लिकेशन i18n

इस प्रकार, मैं पहली बार चीजें प्राप्त करना चाहता हूं ताकि मैं जेएसपी, जावास्क्रिप्ट फाइलों, सर्लेट्स और कहीं और स्क्रॉल करने की आवश्यकता को सीमित कर सकूं, संदेश बंडलों से मूल्यों के साथ हार्ड-कोडेड तारों को प्रतिस्थापित कर सकता हूं।

यहां कोई ढांचा नहीं है। मैं i18n का समर्थन कैसे कर सकता हूं। ध्यान दें कि मैं प्रति दृश्य एक जेएसपी चाहता हूं जो (ए) गुण फ़ाइल से टेक्स्ट लोड करता है और प्रत्येक समर्थित लोकेल के लिए एक अलग जेएसपी नहीं करता है।

मुझे लगता है कि मेरा मुख्य प्रश्न यह है कि क्या मैं कहीं भी 'बैकएंड' में लोकेल सेट कर सकता हूं (यानी लॉगिन में उपयोगकर्ता प्रोफ़ाइल से लोकेल को पढ़ना और सत्र में स्टोर मूल्य) और फिर उम्मीद करें कि जेएसपी पेज सही ढंग से लोड हो पाएंगे प्रत्येक जेएसपी में सही लोकेल खोजने के लिए तर्क जोड़ने के विरोध में सही गुण फ़ाइल से निर्दिष्ट स्ट्रिंग (यानी संदेशों_fr.properties से जब लोकेल फ्रेंच है)।

कोई विचार मैं कैसे संपर्क कर सकता हूं?

+0

[जावा वेब एप्लिकेशन को अंतर्राष्ट्रीयकरण कैसे करें] के संभावित डुप्लिकेट। (Http://stackoverflow.com/questions/4276061/how-to-internationalize-a-java-web-application) – BalusC

उत्तर

18

बातें करते हुए आवेदन अंतर्राष्ट्रीयकरण का ध्यान रखा जाना करने की जरूरत है कि का एक बहुत होते हैं:

लोकेल का पता लगाने

बहुत पहली बात आप के बारे में सोचने की जरूरत अंत उपयोगकर्ता किसी भी स्थान का पता लगाने के लिए है। आप जो समर्थन करना चाहते हैं उसके आधार पर यह आसान या थोड़ा जटिल हो सकता है।

  1. जैसा कि आप निश्चित रूप से जानते हैं, वेब ब्राउज़र HTTP स्वीकार्य-भाषा शीर्षलेख के माध्यम से अंतिम उपयोगकर्ता की पसंदीदा भाषा भेजते हैं। सर्वलेट में इस जानकारी को एक्सेस करना request.getLocale() पर कॉल करने जितना आसान हो सकता है।यदि आप किसी भी फैंसी Locale Detection workflow का समर्थन करने की योजना नहीं बना रहे हैं, तो आप बस इस विधि से चिपके रह सकते हैं।
  2. यदि आपके पास अपने आवेदन में उपयोगकर्ता प्रोफाइल हैं, तो आप इसे पसंदीदा भाषा और पसंदीदा स्वरूपण लोकेल जोड़ना चाहेंगे। ऐसे मामले में आपको उपयोगकर्ता लॉग इन करने के बाद लोकेल को स्विच करने की आवश्यकता होगी।
  3. आप URL- आधारित भाषा स्विचिंग का समर्थन करना चाहेंगे (उदाहरण के लिए: http://deutsch.example.com/ या http://example.com?lang=de)। आपको यूआरएल सूचना के आधार पर वैध लोकेल सेट करना होगा - यह विभिन्न तरीकों से किया जा सकता है (यानी यूआरएल फ़िल्टर)।
  4. आप भाषा स्विचिंग (इसे ड्रॉप-डाउन मेनू या कुछ से चुनकर) का समर्थन करना चाहेंगे, हालांकि मैं इसकी अनुशंसा नहीं करता (जब तक यह बिंदु 3 के साथ संयुक्त नहीं होता)।

JSTL दृष्टिकोण पर्याप्त हो सकता है अगर आप सिर्फ पहली विधि का समर्थन करना चाहते हैं या आपके पास कोई अतिरिक्त निर्भरता (स्प्रिंग फ्रेमवर्क की तरह) जोड़ने के लिए योजना नहीं बना रहे हैं।

हम स्प्रिंग फ्रेमवर्क यह है कि आप लोकेल (जैसे CookieLocaleResolver, AcceptHeaderLocaleResolver, SessionLocaleResolver और LocaleChangeInterceptor) और externalizing तार और स्वरूपण संदेश (spring:message tab देखें) पता लगाने के लिए दोनों का उपयोग कर सकते काफी कुछ अच्छा सुविधाओं की है पर हैं है।
स्प्रिंग फ्रेमवर्क आपको उपरोक्त सभी परिदृश्यों को आसानी से कार्यान्वित करने की अनुमति देगा और यही कारण है कि मैं इसे पसंद करता हूं।

स्ट्रिंग बाह्यीकरण

यह कुछ ऐसा है आसान, सही होना चाहिए? खैर, ज्यादातर यह है - बस उचित टैग का उपयोग करें। क्लाइंट-साइड (जावास्क्रिप्ट) ग्रंथों को बाहरी करने की बात आने पर आपको एकमात्र समस्या का सामना करना पड़ सकता है। कई संभावित दृष्टिकोण हैं, लेकिन मुझे इन दोनों का उल्लेख करते हैं:

  1. (संदेश टैग के साथ) अनुवाद तार के प्रत्येक JSP लिखा सरणी है और केवल ग्राहक कोड में कि सरणी का उपयोग। यह आसान दृष्टिकोण है लेकिन कम रखरखाव योग्य है - आपको वास्तव में मान्य पृष्ठों से मान्य तार लिखना होगा (वे जो वास्तव में आपके क्लाइंट-साइड स्क्रिप्ट को संदर्भित करते हैं)। मैंने पहले ऐसा किया है और मुझ पर विश्वास किया है, यह ऐसा कुछ नहीं है जिसे आप बड़े आवेदन में करना चाहते हैं (लेकिन शायद यह छोटे के लिए सबसे अच्छा समाधान है)।
  2. सिद्धांत में एक और दृष्टिकोण कठिन लग सकता है लेकिन भविष्य में इसे संभालना वास्तव में आसान है। विचार क्लाइंट साइड पर तारों को केंद्रीकृत करना है (उन्हें कुछ सामान्य जावास्क्रिप्ट फ़ाइल में ले जाएं)। इसके बाद आपको अपना स्वयं का सर्वलेट लागू करना होगा जो इस स्क्रिप्ट को अनुरोध पर वापस कर देगा - सामग्री का अनुवाद किया जाना चाहिए। आप यहां जेएसटीएल का उपयोग नहीं कर पाएंगे, आपको सीधे संसाधन बंडलों से स्ट्रिंग प्राप्त करने की आवश्यकता होगी।
    इसे बनाए रखना बहुत आसान है, क्योंकि आपके पास अनुवाद करने योग्य तार जोड़ने के लिए एक केंद्रीय बिंदु होगा।

concatenations

मुझे लगता है कि कहने के लिए नफरत है, लेकिन वास्तव में concatenations localizability नजरिए से दुखदाई है। वे बहुत आम हैं और ज्यादातर लोगों को इसका एहसास नहीं है।

तो फिर सम्मेलन क्या है?

सिद्धांत पर, प्रत्येक अंग्रेजी वाक्य को लक्ष्य भाषा में अनुवादित करने की आवश्यकता होती है।समस्या यह है कि, कई बार ऐसा होता है कि सही अनुवादित संदेश अपने अंग्रेजी समकक्ष की तुलना में अलग-अलग शब्द ऑर्डर का उपयोग करता है (इसलिए अंग्रेजी "सुरक्षा नीति" का अनुवाद पोलिश "पोलिटीका बेज़पिएज़ेंस्टवा" - "नीति" "पोलिटीका" है - ऑर्डर अलग है)।

ठीक है, लेकिन यह सॉफ्टवेयर से कैसे संबंधित है?

वेब अनुप्रयोग में आप इस तरह तार जोड़ सकता है:

String securityPolicy = "Security " + "policy"; 

या इस तरह:

<p><span style="font-weight:bold">Security</span> policy</p> 

दोनों समस्याग्रस्त किया जाएगा। पहले मामले में आपको MessageFormat.format() विधि का उपयोग करना होगा और उदाहरण के लिए तारों को बाहरी करना होगा (उदाहरण के लिए) "Security {0}" और "policy", बाद में आप पूरे पैराग्राफ (पी टैग), की सामग्री को बाहरी रूप से स्पैन टैग समेत बाहरी कर देंगे। मुझे पता है कि यह अनुवादकों के लिए दर्दनाक है लेकिन वास्तव में कोई बेहतर तरीका नहीं है।
कभी-कभी आपको अपने अनुच्छेद में गतिशील सामग्री का उपयोग करना पड़ता है - जेएसटीएल एफएमटी: प्रारूप टैग आपको यहां भी मदद करेगा (यह बैकएंड पक्ष पर चूना संदेशफॉर्मैट काम करता है)।

लेआउट

स्थानीय आवेदन में, यह अक्सर होता है कि अनुवाद तार रास्ता अब अंग्रेजी की तुलना में कर रहे हैं। परिणाम बहुत बदसूरत लग सकता है। किसी भी तरह, आपको शैलियों को ठीक करने की आवश्यकता होगी। दो दृष्टिकोण हैं:

  1. सामान्य शैलियों को समायोजित करके होने वाली समस्याओं को ठीक करें (और प्रार्थना करें कि यह अन्य भाषाओं को तोड़ नहीं देगा)। यह बनाए रखने के लिए बहुत दर्दनाक है।
  2. सीएसएस स्थानीयकरण तंत्र लागू करें। जिस तंत्र के बारे में मैं बात कर रहा हूं उसे डिफ़ॉल्ट, भाषा-स्वतंत्र सीएसएस फ़ाइल और प्रति-भाषा ओवरराइड देना चाहिए। विचार प्रत्येक भाषा के लिए सीएसएस फ़ाइल को ओवरराइड करना है, ताकि आप मांग पर लेआउट समायोजित कर सकें (केवल एक भाषा के लिए)। ऐसा करने के लिए, डिफ़ॉल्ट सीएसएस फ़ाइल के साथ-साथ जेएसपी पृष्ठों में किसी भी शैली परिभाषाओं के बगल में !important कीवर्ड नहीं होना चाहिए। यदि आपको वास्तव में इसका उपयोग करना है, तो उन्हें भाषा-आधारित en.css पर ले जाएं - इससे अन्य भाषाओं को उन्हें संशोधित करने की अनुमति मिल जाएगी।

संस्कृति विशिष्ट मुद्दों

बचें ग्राफिक्स, रंग और ध्वनियों कि पश्चिमी संस्कृति के लिए विशिष्ट हो सकता है का उपयोग कर। यदि आपको वास्तव में इसकी आवश्यकता है, तो कृपया स्थानीयकरण के साधन प्रदान करें। दिशा-संवेदनशील ग्राफिक्स से बचें (क्योंकि जब आप अरबी या हिब्रू कहने के लिए स्थानीयकरण करने का प्रयास करते हैं तो यह एक समस्या होगी)। साथ ही, यह न मानें कि पूरी दुनिया एक ही संख्या का उपयोग कर रही है (यानी अरबी के लिए सच नहीं है)।

तिथियां और समय क्षेत्रों

जावा में समय में दिनांक हैंडलिंग कम से कम आसान नहीं कहने के लिए है। यदि आप ग्रेगोरियन कैलेंडर की तुलना में किसी और चीज का समर्थन नहीं करेंगे, तो आप अंतर्निहित दिनांक और कैलेंडर कक्षाओं तक रह सकते हैं। आप जेएसटीएल एफएमटी का उपयोग कर सकते हैं: टाइमज़ोन, एफएमटी: फॉर्मेटडेट और एफएमटी: जेएसपी में समय क्षेत्र, प्रारूप और पार्स डेट सही ढंग से सेट करने के लिए parseDate।इस तरह formatDate:

मैं दृढ़ता से fmt उपयोग करने के लिए सुझाव है

<fmt:formatDate value="${someController.somedate}" 
    timeZone="${someController.detectedTimeZone}" 
    dateStyle="default" 
    timeStyle="default" /> 

यह वैध (अंतिम उपयोगकर्ता का) समय क्षेत्र में गुप्त दिनांक और समय के लिए महत्वपूर्ण है। इसके अलावा इसे आसानी से समझने योग्य प्रारूप में परिवर्तित करना काफी महत्वपूर्ण है - यही कारण है कि मैं डिफ़ॉल्ट स्वरूपण शैली की अनुशंसा करता हूं।
बीटीडब्ल्यू। समय क्षेत्र का पता लगाना कुछ आसान नहीं है, क्योंकि वेब ब्राउज़र कुछ भी भेजने के लिए बहुत अच्छे नहीं हैं। इसके बजाय, आप या तो उपयोगकर्ता प्राथमिकताओं के पसंदीदा समय क्षेत्र क्षेत्र (यदि आपके पास है) या वर्तमान समय क्षेत्र क्लाइंट साइड स्क्रिप्ट के माध्यम से वेब ब्राउज़र से ऑफसेट प्राप्त कर सकते हैं (Date object's methods देखें)

नंबर और मुद्राओं

नंबर साथ ही मुद्राओं को स्थानीय प्रारूप में परिवर्तित किया जाना चाहिए। यह समान तरीके से किया जाता है तिथियां प्रारूपित करने के लिए (पार्स भी इसी प्रकार से किया जाता है):

<fmt:formatNumber value="1.21" type="currency"/> 

यौगिक संदेशों

आप पहले से ही तार जोड़ लिए नहीं चेतावनी दी गई है। इसके बजाय आप शायद MessgageFormat का उपयोग करेंगे। हालांकि, मुझे अवश्य कहना चाहिए कि आपको यौगिक संदेशों के उपयोग को कम करना चाहिए। ऐसा इसलिए है क्योंकि लक्षित व्याकरण नियम काफी अलग हैं, इसलिए अनुवादकों को न केवल वाक्य को फिर से व्यवस्थित करने की आवश्यकता हो सकती है (इसे प्लेसहोल्डर्स और MessageFormat.format() का उपयोग करके हल किया जाएगा), लेकिन प्रतिस्थापन के आधार पर पूरी वाक्य को अलग-अलग तरीके से अनुवादित करें । मैं आपको कुछ उदाहरण देता हूँ:

// Multiple plural forms 
English: 4 viruses found. 
Polish: Znaleziono 4 wirusy. **OR** Znaleziono 5 wirusów. 

// Conjugation 
English: Program encountered incorrect character | Application encountered incorrect character. 
Polish: Program napotkał nieznaną literę | Aplikacja napotkała nieznaną literę. 

चरित्र एन्कोडिंग

आप जिन भाषाओं में ISO 8859-1 कोड पेज का समर्थन नहीं करता में स्थानीयकरण की योजना बना रहे हैं, तो आप यूनिकोड का समर्थन करने की आवश्यकता होगी - सबसे अच्छा यूटीएफ -8 में पेज एन्कोडिंग सेट करना है। मैंने देखा है लोगों को इस तरह यह कर:

<%@ page contentType="text/html; charset=UTF-8" %> 

मैं आपको चेतावनी देता चाहिए: इस नहीं पर्याप्त है।

<%@page pageEncoding="UTF-8" %> 

इसके अलावा, आप अभी भी पृष्ठ पर शीर्ष लेख में एन्कोडिंग घोषित करने की आवश्यकता होगी केवल सुरक्षा के होने के लिए: आप वास्तव में इस घोषणा जरूरत

<META http-equiv="Content-Type" content="text/html;charset=UTF-8"> 

सूची मैं तुम्हें दे दी है संपूर्ण नहीं है लेकिन यह अच्छा प्रारंभिक बिंदु है। शुभकामनाएं :)

+0

के लिए धन्यवाद उत्कृष्ट जवाब। दुर्भाग्य से, मैं जिस एप्लिकेशन का उपयोग कर रहा हूं वह विशाल है (यह एक बहुत पुरानी परियोजना है)। स्प्रिंग को प्रोजेक्ट में कभी-कभी पेश किया गया था (जो ~ 10 साल आईआईआरसी है) और मैं स्ट्रिंग्स के उपयोग के आवेदन में स्प्रिंग के i18n समर्थन का उपयोग कर रहा हूं। दुर्भाग्यवश, ऐसा प्रतीत नहीं होता है कि किसी ने वास्तव में i18n के बारे में सोचा है, ऐसा लगता है कि मैं एक लंबे और कठिन कार्य के साथ अटक गया हूं ... – NRaf

1

आप टैग के साथ जेएसटीएल मानक टैग लाइब्रेरी का उपयोग कर ऐसा कर सकते हैं। जेएसटीएल विनिर्देश की एक प्रति प्राप्त करें, i8N अध्याय पढ़ें, जो सामान्य पाठ + दिनांक, समय, मुद्रा पर चर्चा करते हैं। बहुत स्पष्ट रूप से लिखा है और आपको दिखाता है कि टैग के साथ आप इसे कैसे कर सकते हैं। आप लोकेल प्रोग्रामेटिक रूप से

1

जैसी चीजें भी सेट कर सकते हैं आप प्रति लोकेल को अलग जेएसपी फ़ाइल रखने की आवश्यकता नहीं है (और नहीं)। कड़ी मेहनत उन चाबियों को समझना है जो i18n-ed नहीं हैं और उन्हें प्रति लोकल फ़ाइल में ले जाएं, कहें, message_en.properties, messages_fr.properties और इसी तरह।

लोकल गणना आपके तर्क के आधार पर कई स्थानों पर हो सकती है। हम डेटाबेस में संग्रहीत उपयोगकर्ता लोकेशंस के साथ-साथ ब्राउज़र लोकेल का समर्थन करते हैं। आपके आवेदन में आने वाले प्रत्येक अनुरोध में "स्वीकार्य-भाषा" शीर्षलेख होगा जो दर्शाता है कि आपके ब्राउज़र को प्राथमिकता के साथ, यानी जापानी पहले और फिर अंग्रेज़ी के साथ कॉन्फ़िगर किया गया है। यदि ऐसा है, तो एप्लिकेशन को message_ja.properties और उन चाबियों के लिए पढ़ना चाहिए जो उस फ़ाइल में नहीं हैं, संदेशों_en.properties पर फ़ॉलबैक। डेटाबेस के अंदर संग्रहीत उपयोगकर्ता लोकेशंस के लिए भी यह सही हो सकता है। कृपया ध्यान दें कि मानक ब्राउज़र में भाषा को स्विच करने के लिए है और सामग्री को i18n-ed होने की उम्मीद है। (हमने शुरुआत में डेटाबेस में लोकेल को संग्रहीत करने के साथ शुरू किया और फिर ब्राउज़र से स्थानीय लोगों का समर्थन करने के लिए स्थानांतरित हो गया)। इसके अलावा आपको किसी भी डिफ़ॉल्ट की आवश्यकता होगी क्योंकि अनुवादक अंग्रेजी (मुख्य भाषा फ़ाइल) से अन्य भाषाओं में प्रतिलिपि कुंजी और मूल्यों को याद करते हैं, इसलिए आपको अन्य फ़ाइलों में नहीं होने वाले मानों के लिए अंग्रेज़ी में डिफ़ॉल्ट होना होगा।

Ive भी mygengo बहुत उपयोगी पाया गया है जब किसी विशेष भाषा को जानने वाले अन्य लोगों को अनुवाद नौकरी देते हुए, यह हमें बहुत समय बचाता है।

संबंधित मुद्दे