प्रतिक्रिया / Redux और बहुभाषी (अंतर्राष्ट्रीयकरण) ऐप्स - आर्किटेक्चर


119

मैं एक ऐप बना रहा हूं, जिसे कई भाषाओं और स्थानों में उपलब्ध होना चाहिए।

मेरा प्रश्न विशुद्ध रूप से तकनीकी नहीं है, बल्कि वास्तुकला के बारे में है, और इस समस्या को हल करने के लिए लोग वास्तव में उत्पादन में उपयोग कर रहे हैं। मुझे उसके लिए कहीं भी कोई "रसोई की किताब" नहीं मिली, इसलिए मैं अपनी पसंदीदा क्यू / ए वेबसाइट की ओर रुख कर रहा हूं :)

यहाँ मेरी आवश्यकताएं हैं (वे वास्तव में "मानक" हैं):

  • उपयोगकर्ता भाषा (तुच्छ) चुन सकता है
  • भाषा बदलने पर, इंटरफ़ेस को नई चयनित भाषा में स्वचालित रूप से अनुवाद करना चाहिए
  • मैं इस समय संख्याओं, तारीखों आदि को लेकर बहुत चिंतित नहीं हूं, मैं सिर्फ अनुवादों का सरल समाधान चाहता हूं

यहाँ संभव समाधान मैं सोच सकता हूँ:

प्रत्येक घटक अलगाव में अनुवाद के साथ सौदा करता है

इसका मतलब है कि प्रत्येक घटक के लिए उदाहरण के लिए en.json, fr.json आदि फाइलों का एक सेट है, इसके साथ अनुवादित स्ट्रिंग्स के साथ। और चयनित भाषा के आधार पर उन लोगों से मूल्यों को पढ़ने में मदद करने के लिए एक सहायक कार्य करता है।

  • प्रो: रिएक्ट दर्शन का अधिक सम्मान, प्रत्येक घटक "स्टैंडअलोन" है
  • विपक्ष: आप किसी फ़ाइल में सभी अनुवादों को केंद्रीकृत नहीं कर सकते हैं (उदाहरण के लिए किसी और को एक नई भाषा जोड़ने के लिए)
  • विपक्ष: आपको अभी भी वर्तमान भाषा को एक प्रोप के रूप में पारित करने की आवश्यकता है, प्रत्येक खूनी घटक और उनके बच्चों में

प्रत्येक घटक प्रॉप्स के माध्यम से अनुवाद प्राप्त करता है

इसलिए उन्हें वर्तमान भाषा के बारे में पता नहीं है, वे बस स्ट्रिप्स की एक सूची लेते हैं, जो कि वर्तमान भाषा से मेल खाने के लिए होती है

  • प्रो: चूंकि वे तार "ऊपर से" आ रहे हैं, इसलिए उन्हें कहीं पर केंद्रीकृत किया जा सकता है
  • विपक्ष: प्रत्येक घटक अब अनुवाद प्रणाली में बंधा हुआ है, आप सिर्फ एक का फिर से उपयोग नहीं कर सकते हैं, आपको हर बार सही तार निर्दिष्ट करने की आवश्यकता है

आप प्रॉम्प्स को थोड़ा बाईपास करते हैं और संभवतः वर्तमान भाषा को पारित करने के लिए संदर्भ चीज़ का उपयोग करते हैं

  • प्रो: यह ज्यादातर पारदर्शी है, वर्तमान भाषा और / या हर समय सहारा के माध्यम से अनुवाद करने की जरूरत नहीं है
  • विपक्ष: यह उपयोग करने के लिए बोझिल लग रहा है

यदि आपके पास कोई अन्य विचार है, तो कृपया कहें!

आप इसे कैसे करते हो?


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

1
दरअसल facebook.github.io/react/docs/context.html के अनुसार , वर्तमान भाषा को साझा करने के लिए संदर्भ का उपयोग करना वैध उपयोग के मामलों में से एक है। अब मैं जिस दृष्टिकोण की कोशिश कर रहा हूं, वह इस विशेष घटक के लिए तार निकालने के तर्क से निपटने के लिए एक उच्चतर आदेश घटक का उपयोग करना है (शायद कुछ कुंजी पर आधारित)
एंटोनी जौसोइन

1
हो सकता है कि आप झटपट देख भी लें । वे इस समस्या से पूरी तरह से अलग तरीके से निपटते हैं और इसे फ्रंट अलामा में ऑप्टिमाइज़ली (उर्फ डोम को लोड करने के बाद बदल देते हैं)।
मार्सेल पैनसे

1
बिल्कुल बुरा नही! यह वास्तव में एक पूरी तरह से अलग जानवर है (जो आपको एक ऐसी सेवा से जोड़ता है, जिसे आपको अपनी वेबसाइट के बढ़ने पर भुगतान करने की आवश्यकता हो सकती है), लेकिन मुझे यह विचार पसंद है और यह वास्तव में एक छोटी वेबसाइट के लिए इसके लायक है जिसे आपको जल्दी से चलाने की आवश्यकता है!
एंटोनी जौसोइन

4
इसके अलावा, आप यह उल्लेख करना चाहते हैं कि आप "वे" कहने के बजाय इंस्टेंट के सह संस्थापक हैं, जैसे कि आपके पास उनके साथ करने के लिए कुछ भी नहीं है :)
एंटोनी जौसोइन

जवाबों:


110

काफी कुछ समाधानों की कोशिश करने के बाद, मुझे लगता है कि मैंने एक ऐसा पाया जो अच्छी तरह से काम करता है और रिएक्ट 0.14 के लिए एक मुहावरेदार समाधान होना चाहिए (अर्थात यह मिश्रण का उपयोग नहीं करता है, लेकिन उच्च आदेश घटक) ( संपादित करें : पाठ्यक्रम के रिएक्ट 15 के साथ भी पूरी तरह से ठीक है! )।

तो यहाँ समाधान, नीचे से शुरू (व्यक्तिगत घटकों):

घटक

केवल एक चीज की आपके घटक को (सम्मेलन द्वारा) आवश्यकता होगी, एक stringsसहारा है। यह एक ऐसी वस्तु होनी चाहिए जिसमें आपके कंपोनेंट की जरूरत के विभिन्न तार हों, लेकिन वास्तव में इसका आकार आपके ऊपर है।

इसमें डिफ़ॉल्ट अनुवाद शामिल हैं, इसलिए आप किसी भी अनुवाद को प्रदान करने की आवश्यकता के बिना घटक का उपयोग कहीं और कर सकते हैं (यह डिफ़ॉल्ट भाषा के साथ बॉक्स से बाहर काम करेगा, इस उदाहरण में अंग्रेजी)

import { default as React, PropTypes } from 'react';
import translate from './translate';

class MyComponent extends React.Component {
    render() {

        return (
             <div>
                { this.props.strings.someTranslatedText }
             </div>
        );
    }
}

MyComponent.propTypes = {
    strings: PropTypes.object
};

MyComponent.defaultProps = {
     strings: {
         someTranslatedText: 'Hello World'
    }
};

export default translate('MyComponent')(MyComponent);

उच्चतर आदेश घटक

पिछले स्निपेट पर, आपने इसे अंतिम पंक्ति पर देखा होगा: translate('MyComponent')(MyComponent)

translate इस मामले में एक उच्च आदेश घटक है जो आपके घटक को लपेटता है, और कुछ अतिरिक्त कार्यक्षमता प्रदान करता है (यह निर्माण प्रतिक्रिया के पिछले संस्करणों के मिश्रण को बदल देता है)।

पहला तर्क एक कुंजी है जिसका उपयोग अनुवाद फ़ाइल में अनुवाद देखने के लिए किया जाएगा (मैंने यहां घटक के नाम का उपयोग किया था, लेकिन यह कुछ भी हो सकता है)। दूसरा एक (नोटिस कि फ़ंक्शन करी है, ES7 सज्जाकार की अनुमति देने के लिए) लपेटने के लिए घटक है।

यहाँ अनुवाद घटक के लिए कोड है:

import { default as React } from 'react';
import en from '../i18n/en';
import fr from '../i18n/fr';

const languages = {
    en,
    fr
};

export default function translate(key) {
    return Component => {
        class TranslationComponent extends React.Component {
            render() {
                console.log('current language: ', this.context.currentLanguage);
                var strings = languages[this.context.currentLanguage][key];
                return <Component {...this.props} {...this.state} strings={strings} />;
            }
        }

        TranslationComponent.contextTypes = {
            currentLanguage: React.PropTypes.string
        };

        return TranslationComponent;
    };
}

यह जादू नहीं है: यह सिर्फ संदर्भ से वर्तमान भाषा को पढ़ेगा (और यह संदर्भ कोड आधार पर पूरी तरह से खून नहीं करता है, बस यहां इस आवरण में उपयोग किया जाता है), और फिर लोड की गई फ़ाइलों से संबंधित स्ट्रिंग ऑब्जेक्ट प्राप्त करें। तर्क का यह टुकड़ा इस उदाहरण में काफी भोला है, जिस तरह से आप वास्तव में चाहते हैं।

महत्वपूर्ण टुकड़ा यह है कि यह वर्तमान भाषा को संदर्भ से लेता है और प्रदान की गई कुंजी को देखते हुए इसे तार में परिवर्तित करता है।

पदानुक्रम के शीर्ष पर

रूट घटक पर, आपको बस अपनी वर्तमान स्थिति से वर्तमान भाषा सेट करने की आवश्यकता है। निम्न उदाहरण फ्लक्स जैसे कार्यान्वयन के रूप में Redux का उपयोग कर रहा है, लेकिन इसे आसानी से किसी अन्य ढांचे / पैटर्न / लाइब्रेरी का उपयोग करके परिवर्तित किया जा सकता है।

import { default as React, PropTypes } from 'react';
import Menu from '../components/Menu';
import { connect } from 'react-redux';
import { changeLanguage } from '../state/lang';

class App extends React.Component {
    render() {
        return (
            <div>
                <Menu onLanguageChange={this.props.changeLanguage}/>
                <div className="">
                    {this.props.children}
                </div>

            </div>

        );
    }

    getChildContext() {
        return {
            currentLanguage: this.props.currentLanguage
        };
    }
}

App.propTypes = {
    children: PropTypes.object.isRequired,
};

App.childContextTypes = {
    currentLanguage: PropTypes.string.isRequired
};

function select(state){
    return {user: state.auth.user, currentLanguage: state.lang.current};
}

function mapDispatchToProps(dispatch){
    return {
        changeLanguage: (lang) => dispatch(changeLanguage(lang))
    };
}

export default connect(select, mapDispatchToProps)(App);

और अनुवाद फ़ाइलों को पूरा करने के लिए:

अनुवाद फ़ाइलें

// en.js
export default {
    MyComponent: {
        someTranslatedText: 'Hello World'
    },
    SomeOtherComponent: {
        foo: 'bar'
    }
};

// fr.js
export default {
    MyComponent: {
        someTranslatedText: 'Salut le monde'
    },
    SomeOtherComponent: {
        foo: 'bar mais en français'
    }
};

आप लोग क्या सोचते हैं?

मुझे लगता है कि मैं अपने सवाल से बचने की कोशिश कर रहा था कि सभी समस्या का हल हो रहा है: अनुवाद तर्क स्रोत कोड पर पूरी तरह से खून नहीं करता है, यह काफी अलग-थलग है और इसके बिना घटकों का पुन: उपयोग करने की अनुमति देता है।

उदाहरण के लिए, MyComponent को अनुवाद द्वारा लिपटा जाने की आवश्यकता नहीं है (और अलग किया जा सकता है, यह अनुमति देता है कि यह किसी और के द्वारा फिर से उपयोग करने के लिए stringsअपने स्वयं के माध्यम से प्रदान करना चाहता है।

[संपादित करें: ३१/०३/२०१६]: मैंने हाल ही में एक रेट्रोस्पेक्टिव बोर्ड (एजाइल रेट्रोस्पेक्टिव्स के लिए) पर काम किया, जो रिएक्ट एंड रेडक्स के साथ बनाया गया है, और बहुभाषी है। चूंकि काफी लोगों ने टिप्पणियों में वास्तविक जीवन का उदाहरण मांगा है, इसलिए यह है:

आप यहां कोड पा सकते हैं: https://github.com/antoinejaussoin/retro-board/tree/master


यह एक अच्छा समाधान है .. अगर आप कुछ महीनों के बाद भी बोर्ड पर हैं तो सोच रहे हैं? मुझे इस ऑनलाइन के लिए पैटर्न पर सलाह के तरीके में ज्यादा सलाह नहीं मिली है
डेमन

2
मैं वास्तव में हूं, मैंने पाया कि पूरी तरह से काम करने के लिए (मेरी जरूरतों के लिए)। यह डिफ़ॉल्ट रूप से अनुवाद के बिना घटक का काम करता है, और अनुवाद इसके बारे में पता किए बिना घटक इसके ऊपर आता है
एंटोनी जौसोइन

1
@ l.cetinsoy आप dangerouslySetInnerHTMLप्रोप का उपयोग कर सकते हैं , बस निहितार्थ का ध्यान रखें (इनपुट को मैन्युअल रूप से साफ करें)। देखें facebook.github.io/react/tips/dangerously-set-inner-html.html
Teodor Sandu

6
क्या कोई कारण है कि आपने प्रतिक्रिया-intl की कोशिश क्यों नहीं की?
सुरेश सीसी

1
वास्तव में इस समाधान की तरह। एक चीज जो मैं जोड़ूंगा, जो हमें स्थिरता और समय की बचत के लिए बहुत उपयोगी लगी, वह यह कि अगर आपके पास बहुत सारे घटक हैं जिनमें सामान्य तार हैं तो आप चर का लाभ उठा सकते हैं और वस्तुओं पर फैल सकते हैं जैसेconst formStrings = { cancel, create, required }; export default { fooForm: { ...formStrings, foo: 'foo' }, barForm: { ...formStrings, bar: 'bar' } }
Huw Davies

18

मेरे अनुभव से सबसे अच्छा तरीका एक i18n redux राज्य बनाना और कई कारणों से इसका उपयोग करना है:

1- यह आपको डेटाबेस, स्थानीय फ़ाइल या यहां तक ​​कि ईजेएस या जेड जैसे टेम्पलेट इंजन से प्रारंभिक मूल्य पारित करने की अनुमति देगा

2- जब उपयोगकर्ता भाषा बदलता है तो आप यूआई को रीफ्रेश किए बिना भी पूरी एप्लिकेशन भाषा बदल सकते हैं।

3- जब उपयोगकर्ता भाषा बदलता है तो यह आपको एपीआई, स्थानीय फ़ाइल या यहां तक ​​कि स्थिरांक से नई भाषा को पुनः प्राप्त करने की अनुमति देगा

4-आप अन्य महत्वपूर्ण चीजों को भी बचा सकते हैं जैसे टाइमजोन, मुद्रा, दिशा (RTL / LTR) और उपलब्ध भाषाओं की सूची

5- आप परिवर्तन भाषा को एक सामान्य रिडक्स क्रिया के रूप में परिभाषित कर सकते हैं

6- आपके पास एक स्थान पर आपके बैकएंड और फ्रंट एंड स्ट्रिंग्स हो सकते हैं, उदाहरण के लिए, मेरे मामले में मैं स्थानीयकरण के लिए i18n-नोड का उपयोग करता हूं और जब उपयोगकर्ता UI भाषा बदलता है तो मैं सिर्फ एक सामान्य एपीआई कॉल करता हूं और बैकएंड में, मैं बस वापस आ जाता हूं i18n.getCatalog(req)यह केवल वर्तमान भाषा के लिए सभी उपयोगकर्ता स्ट्रिंग लौटाएगा

I18n प्रारंभिक अवस्था के लिए मेरा सुझाव है:

{
  "language":"ar",
  "availableLanguages":[
    {"code":"en","name": "English"},
    {"code":"ar","name":"عربي"}
  ],
  "catalog":[
     "Hello":"مرحباً",
     "Thank You":"شكراً",
     "You have {count} new messages":"لديك {count} رسائل جديدة"
   ],
  "timezone":"",
  "currency":"",
  "direction":"rtl",
}

I18n के लिए अतिरिक्त उपयोगी मॉड्यूल:

1- स्ट्रिंग-टेम्प्लेट आपको उदाहरण के लिए अपनी कैटलॉग स्ट्रिंग्स के बीच मानों को इंजेक्ट करने की अनुमति देगा:

import template from "string-template";
const count = 7;
//....
template(i18n.catalog["You have {count} new messages"],{count}) // لديك ٧ رسائل جديدة

2- मानव-प्रारूप यह मॉड्यूल आपको उदाहरण के लिए, किसी संख्या को / से मानव पठनीय स्ट्रिंग में परिवर्तित करने की अनुमति देगा:

import humanFormat from "human-format";
//...
humanFormat(1337); // => '1.34 k'
// you can pass your own translated scale, e.g: humanFormat(1337,MyScale)

3 momentjs सबसे प्रसिद्ध दिनांक और समय NPM पुस्तकालय, आप पल अनुवाद कर सकते हैं, लेकिन यह पहले से ही एक अंतर्निहित अनुवाद केवल आपके उदाहरण के लिए वर्तमान स्थिति भाषा पारित करने के लिए की जरूरत है:

import moment from "moment";

const umoment = moment().locale(i18n.language);
umoment.format('MMMM Do YYYY, h:mm:ss a'); // أيار مايو ٢ ٢٠١٧، ٥:١٩:٥٥ م

अपडेट (14/06/2019)

वर्तमान में, प्रतिक्रिया के संदर्भ एपीआई ( रिडक्स के बिना) का उपयोग करके एक ही अवधारणा को लागू करने के लिए कई रूपरेखाएं हैं, मैंने व्यक्तिगत रूप से I18next की सिफारिश की है


क्या यह दृष्टिकोण दो से अधिक भाषाओं के लिए भी काम करेगा? कैटलॉग की स्थापना को ध्यान में रखते हुए
टेम्परानोवा

नीचे मतदान हुआ। इस सवाल का जवाब नहीं है। ओपी ने एक आर्किटेक्चर विचार के लिए कहा, न कि सुझाव या किसी i18n पुस्तकालय की तुलना।
TrungDQ

9
मैंने i18n कैटलॉग को redux स्टेट के रूप में सुझाया, ऐसा लगता है कि आप redux को नहीं समझते हैं
Fareed Alnamrouti

5

एंटोनी का घोल ठीक काम करता है, लेकिन इसके कुछ उपाय हैं:

  • यह सीधे रिएक्ट संदर्भ का उपयोग करता है, जिसे मैं पहले से ही Redux का उपयोग करने से बचने के लिए करता हूं
  • यह एक फ़ाइल से सीधे वाक्यांशों को आयात करता है, जो समस्याग्रस्त हो सकता है यदि आप रनटाइम, क्लाइंट-साइड में आवश्यक भाषा प्राप्त करना चाहते हैं
  • यह किसी भी i18n लाइब्रेरी का उपयोग नहीं करता है, जो हल्का है, लेकिन आपको बहुवचन और इंटरलेक्शन जैसी आसान अनुवाद कार्यक्षमता तक पहुंच नहीं देता है

कारण है कि हम बनाया है कि redux-बहुभाषी दोनों Redux और Airbnb के के शीर्ष पर बहुशब्दविद
(मैं लेखकों में से एक हूं)

यह प्रावधान :

  • आपके Redux स्टोर में भाषा और संबंधित संदेशों को संग्रहीत करने के लिए एक रिड्यूसर। आप दोनों द्वारा आपूर्ति कर सकते हैं:
    • एक मिडलवेयर जिसे आप विशिष्ट कार्रवाई को पकड़ने के लिए कॉन्फ़िगर कर सकते हैं, वर्तमान भाषा को घटा सकते हैं और संबंधित संदेश प्राप्त / प्राप्त कर सकते हैं।
    • का प्रत्यक्ष प्रेषण setLanguage(lang, messages)
  • एक getP(state)चयनकर्ता जो P4 तरीकों को उजागर करने वाली वस्तु को पुनः प्राप्त करता है:
    • t(key): मूल पॉलीग्लॉट टी फ़ंक्शन
    • tc(key): पूंजीकृत अनुवाद
    • tu(key): ऊपरी आवरण अनुवाद
    • tm(morphism)(key): कस्टम रूपांतरित अनुवाद
  • एक getLocale(state)चयनकर्ता वर्तमान भाषा पाने के लिए
  • एक translateउच्च आदेश घटक प्रॉम्प्स में pऑब्जेक्ट को इंजेक्ट करके अपने रिएक्ट घटकों को बढ़ाने के लिए

सरल उपयोग उदाहरण:

प्रेषण नई भाषा:

import setLanguage from 'redux-polyglot/setLanguage';

store.dispatch(setLanguage('en', {
    common: { hello_world: 'Hello world' } } }
}));

घटक में:

import React, { PropTypes } from 'react';
import translate from 'redux-polyglot/translate';

const MyComponent = props => (
  <div className='someId'>
    {props.p.t('common.hello_world')}
  </div>
);
MyComponent.propTypes = {
  p: PropTypes.shape({t: PropTypes.func.isRequired}).isRequired,
}
export default translate(MyComponent);

अगर आपके कोई सवाल / सुझाव हो तो कृपया मुझे बताएँ!


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

हाय @ जलील, क्या मिडलवेयर के साथ कहीं भी एक पूर्ण उदाहरण है?
अर्कडीबी

हाय @ArkadyB, हम इसे कई परियोजनाओं पर उत्पादन पर उपयोग करते हैं जो खुले-खट्टे नहीं हैं। आप मॉड्यूल README: npmjs.com/package/redux-polyglot पर अधिक जानकारी प्राप्त कर सकते हैं। क्या आपको इसे इस्तेमाल करने में कोई प्रश्न / कठिनाई है?
जलील

इस और polyglot.js के साथ मेरा प्रमुख मुद्दा यह है कि यह पूरी तरह से पीओ फाइलों के ऊपर निर्माण के बजाय पहिया का फिर से आविष्कार कर रहा है। यह वैकल्पिक लाइब्रेरी npmjs.com/package/redux-i18n का वादा करती है । मुझे नहीं लगता कि यह बहुत अलग है - यह केवल पीओ फ़ाइलों से कन्वर्ट करने के लिए एक अतिरिक्त परत प्रदान कर रहा है।
icc97

2

मेरे शोध से यह प्रतीत होता है कि जावास्क्रिप्ट, आईसीयू और गेटेक्स्ट में i18n के लिए दो मुख्य दृष्टिकोण हैं ।

मैंने केवल गेटटेक्स्ट का उपयोग किया है, इसलिए मैं पक्षपाती हूं।

मुझे क्या आश्चर्य है कि समर्थन कितना खराब है। मैं PHP दुनिया से आता हूं, या तो CakePHP या वर्डप्रेस। उन दोनों स्थितियों में, यह एक बुनियादी मानक है कि सभी तार बस से घिरे होते हैं __(''), फिर आगे की रेखा के नीचे आपको पीओ फाइलों का उपयोग करके आसानी से अनुवाद मिलता है।

gettext

आपको स्ट्रिंग्स को फॉर्मेट करने के लिए स्प्रिंटफ की परिचितता प्राप्त होती है और पीओ फाइलों को हजारों विभिन्न एजेंसियों द्वारा आसानी से अनुवादित किया जाएगा।

दो लोकप्रिय विकल्प हैं:

  1. i18next , इस arkency.com ब्लॉग पोस्ट द्वारा वर्णित उपयोग के साथ
  2. जेड , संतरी द्वारा वर्णित उपयोग के साथ। पोस्ट और इस प्रतिक्रिया + Redux पोस्ट ,

दोनों में गेटटेक्स्ट स्टाइल सपोर्ट, स्ट्रिंग्स के स्प्रिंटफ स्टाइल फॉर्मेटिंग और पीओ फाइलों को इम्पोर्ट / एक्सपोर्ट है।

i18next का एक रिएक्ट एक्सटेंशन है जो स्वयं द्वारा विकसित किया गया है। जेड नहीं है। Sentry.io रिएक्ट के साथ जेड के कस्टम एकीकरण का उपयोग करते हुए दिखाई देते हैं। प्रतिक्रिया + Redux पोस्ट , उपयोग करने का सुझाव

उपकरण: जेड + po2json + jsxgettext

हालाँकि, जैद एक अधिक गेटटेक्स्ट फ़ोकसड कार्यान्वयन जैसा लगता है - यह इरादा व्यक्त किया गया है, जहां i18next के रूप में बस एक विकल्प के रूप में है।

आईसीयू

यह अनुवाद के आसपास के मामलों के लिए अधिक समर्थन करता है, उदाहरण के लिए लिंग से निपटने के लिए। मुझे लगता है कि अगर आपको और अधिक जटिल भाषाओं में अनुवाद करना है तो आप इससे लाभ देखेंगे।

इसके लिए एक लोकप्रिय विकल्प मैसेजफॉर्मैट.जेएस है । इस संतरी .io ब्लॉग ट्यूटोरियल में संक्षेप में चर्चा की गई । messageformat.js वास्तव में उसी व्यक्ति द्वारा विकसित किया गया है जिसने जेड लिखा था। वह ICU का उपयोग करने के लिए काफी दावे करता है :

मेरी राय में जेड पूर्ण है। मुझे बग्स को ठीक करने में खुशी हो रही है, लेकिन आम तौर पर पुस्तकालय में अधिक जोड़ने के लिए दिलचस्पी नहीं है।

मैं मैसेजफॉर्मैट.जेएस भी बनाए रखता हूं। यदि आपको विशेष रूप से गेटेक्स्ट कार्यान्वयन की आवश्यकता नहीं है, तो मैं इसके बजाय MessageFormat का उपयोग करने का सुझाव दे सकता हूं, क्योंकि इसमें बहुवचन / लिंग के लिए बेहतर समर्थन है और इसमें अंतर्निहित डेटा है।

किसी की तुलना

स्प्रिंट के साथ गेटटेक्स्ट:

i18next.t('Hello world!');
i18next.t(
    'The first 4 letters of the english alphabet are: %s, %s, %s and %s', 
    { postProcess: 'sprintf', sprintf: ['a', 'b', 'c', 'd'] }
);

messageformat.js ( गाइड पढ़ने से मेरा सबसे अच्छा अनुमान ):

mf.compile('Hello world!')();
mf.compile(
    'The first 4 letters of the english alphabet are: {s1}, {s2}, {s3} and {s4}'
)({ s1: 'a', s2: 'b', s3: 'c', s4: 'd' });

नीचे मतदान हुआ। इस सवाल का जवाब नहीं है। ओपी ने एक आर्किटेक्चर विचार के लिए कहा, न कि सुझाव या किसी i18n पुस्तकालय की तुलना।
TrungDQ

@TrungDQ यह वही है जो ओपी ने पूछा: "मेरा प्रश्न विशुद्ध रूप से तकनीकी नहीं है, बल्कि वास्तुकला के बारे में है, और पैटर्न जो लोग वास्तव में इस समस्या को हल करने के लिए उत्पादन में उपयोग कर रहे हैं ।" । ये दो पैटर्न हैं जिनका उपयोग उत्पादन में किया जा रहा है।
ic9797 27'17

मेरी राय में यह उत्तर मुझे वह जानकारी प्रदान नहीं करता है जिसकी मुझे (और अन्य को) तलाश है। आपके द्वारा दी गई जानकारी उपयोगी है, लेकिन शायद एक और प्रश्न के लिए। मैं सिर्फ सही उत्तर को शीर्ष तक पहुंचाने के लिए अपने योगदान में योगदान करना चाहता हूं (मुझे उम्मीद है)।
TrungDQ

@TrungDQ यदि आप जिस चीज़ की तलाश में हैं, तो बस उसी को अपवोट करें, जिसे आपने उपयोग किया है और दूसरों को नजरअंदाज करने के बजाए अनदेखा कर दें, जो कि आपके द्वारा पूछे गए प्रश्न के विशिष्ट भाग से मेल नहीं खाते हैं।
icc97

1

अगर अभी तक https://react.i18next.com/ पर नज़र नहीं रखी है तो एक अच्छी सलाह हो सकती है। यह i18next पर आधारित है: एक बार सीखें - हर जगह अनुवाद करें।

आपका कोड कुछ इस तरह दिखाई देगा:

<div>{t('simpleContent')}</div>
<Trans i18nKey="userMessagesUnread" count={count}>
  Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
</Trans>

के लिए नमूने के साथ आता है:

  • webpack
  • सीआरए
  • expo.js
  • next.js
  • स्टोरीबुक एकीकरण
  • कोलाहलपूर्ण मद्यपानोत्सव
  • Dat
  • ...

https://github.com/i18next/react-i18next/tree/master/example

इसके अलावा कि आपको विकास के दौरान और बाद में अपने अनुवादकों के लिए वर्कफ़्लो पर विचार करना चाहिए -> https://www.youtube.com/watch?v=9NOzJhgmyQE


इस सवाल का जवाब नहीं है। ओपी ने एक आर्किटेक्चर विचार के लिए कहा, न कि सुझाव या किसी i18n पुस्तकालय की तुलना।
त्रियुंडक्यू

@TrungDQ मेरे जवाब पर आपकी टिप्पणी के साथ जो आपने डाउनवोट किया था - ओपी ने उत्पादन में उपयोग किए जाने वाले वर्तमान समाधानों के लिए कहा। हालाँकि मैंने अपने जवाब में i18next को फरवरी से वापस करने का सुझाव दिया था ।
icc97

0

मैं क्रिएट-रिएक्शन-ऐप का उपयोग करके एक सरल समाधान प्रस्तावित करना चाहता हूं ।

आवेदन हर भाषा के लिए अलग से बनाया जाएगा, इसलिए पूरे अनुवाद तर्क को आवेदन से बाहर कर दिया जाएगा।

वेब सर्वर स्वीकार-भाषा हेडर के आधार पर , या मैन्युअल रूप से कुकी सेट करके, सही भाषा को स्वचालित रूप से काम करेगा ।

अधिकतर, हम भाषा को एक से अधिक बार नहीं बदलते हैं, यदि कभी भी)

अनुवाद डेटा उसी घटक फ़ाइल के अंदर रखा जाता है, जो इसका उपयोग शैलियों, HTML और कोड के साथ करता है।

और यहां हमारे पास पूरी तरह से स्वतंत्र घटक है जो अपने स्वयं के राज्य, दृश्य, अनुवाद के लिए जिम्मेदार है:

import React from 'react';
import {withStyles} from 'material-ui/styles';
import {languageForm} from './common-language';
const {REACT_APP_LANGUAGE: LANGUAGE} = process.env;
export let language; // define and export language if you wish
class Component extends React.Component {
    render() {
        return (
            <div className={this.props.classes.someStyle}>
                <h2>{language.title}</h2>
                <p>{language.description}</p>
                <p>{language.amount}</p>
                <button>{languageForm.save}</button>
            </div>
        );
    }
}
const styles = theme => ({
    someStyle: {padding: 10},
});
export default withStyles(styles)(Component);
// sets laguage at build time
language = (
    LANGUAGE === 'ru' ? { // Russian
        title: 'Транзакции',
        description: 'Описание',
        amount: 'Сумма',
    } :
    LANGUAGE === 'ee' ? { // Estonian
        title: 'Tehingud',
        description: 'Kirjeldus',
        amount: 'Summa',
    } :
    { // default language // English
        title: 'Transactions',
        description: 'Description',
        amount: 'Sum',
    }
);

भाषा वातावरण चर को अपने package.json में जोड़ें

"start": "REACT_APP_LANGUAGE=ru npm-run-all -p watch-css start-js",
"build": "REACT_APP_LANGUAGE=ru npm-run-all build-css build-js",

बस इतना ही!

इसके अलावा मेरे मूल उत्तर में प्रत्येक अनुवाद के लिए सिंगल जोंस फाइल के साथ अधिक अखंड दृष्टिकोण शामिल था:

लैंग / ru.json

{"hello": "Привет"}

lib / lang.js

export default require(`../lang/${process.env.REACT_APP_LANGUAGE}.json`);

src / App.jsx

import lang from '../lib/lang.js';
console.log(lang.hello);

क्या यह केवल संकलन के समय काम नहीं करेगा? उपयोगकर्ता के लिए मक्खी पर भाषा बदलने की क्षमता के बिना? यह एक अलग उपयोग-मामला होगा।
एंटोनी जौसोइन

जरूरत की हर भाषा के लिए ऐप संकलित किया जाएगा। वेब सर्वर "एक्सेप्ट-लैंग्वेज" हेडर के आधार पर या फ़्लाई पर उपयोगकर्ता द्वारा निर्धारित कुकी के आधार पर, स्वचालित रूप से सही संस्करण पर काम करेगा। ऐसा करने से, पूरे अनुवाद तर्क को ऐप से बाहर ले जाया जा सकता है।
इगोर सुखारेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.