React / Redux 및 다국어 (국제화) 앱-아키텍처


119

여러 언어와 로케일로 사용할 수 있어야하는 앱을 만들고 있습니다.

제 질문은 순전히 기술적 인 것이 아니라 아키텍처와 사람들이 실제로이 문제를 해결하기 위해 프로덕션에서 사용하는 패턴에 관한 것입니다. 이에 대한 "요리 책"을 찾을 수 없어서 제가 좋아하는 Q / A 웹 사이트로 이동합니다. :)

내 요구 사항은 다음과 같습니다 (실제로 "표준"임).

  • 사용자는 언어를 선택할 수 있습니다 (사소한)
  • 언어를 변경하면 인터페이스가 새로 선택한 언어로 자동 번역되어야합니다.
  • 지금은 숫자, 날짜 등의 서식을 지정하는 것이 너무 걱정되지 않습니다. 문자열 만 번역하는 간단한 솔루션을 원합니다.

제가 생각할 수있는 가능한 해결책은 다음과 같습니다.

각 구성 요소는 개별적으로 번역을 처리합니다.

즉, 각 구성 요소에는 예를 들어 번역 된 문자열과 함께 en.json, fr.json 등의 파일 집합이 있습니다. 그리고 선택한 언어에 따라 값을 읽는 데 도움이되는 도우미 기능.

  • 장점 : React 철학을 더 존중하며 각 구성 요소는 "독립형"입니다.
  • 단점 : 파일의 모든 번역을 중앙 집중화 할 수 없습니다 (예 : 다른 사람이 새 언어를 추가하도록하기 위해)
  • 단점 : 모든 피 묻은 구성 요소와 그 자녀에게 현재 언어를 소품으로 전달해야합니다.

각 구성 요소는 소품을 통해 번역을받습니다.

따라서 그들은 현재 언어를 인식하지 못하고 현재 언어와 일치하는 소품으로 문자열 목록을 가져옵니다.

  • 장점 : 이러한 문자열은 "상단에서"나오기 때문에 어딘가에 집중할 수 있습니다.
  • 단점 : 이제 각 구성 요소가 번역 시스템에 연결되어 있으므로 다시 사용할 수 없으며 매번 올바른 문자열을 지정해야합니다.

소품을 약간 우회하고 컨텍스트를 사용 하여 현재 언어를 전달합니다.

  • 장점 : 대부분 투명하며 항상 소품을 통해 현재 언어 및 / 또는 번역을 전달할 필요가 없습니다.
  • 단점 : 사용이 번거로워 보입니다.

다른 아이디어가 있으면 말 해주세요!

어떻게하나요?


2
저는 소품으로 전달되는 번역 문자열이있는 키 객체의 아이디어를 선호합니다. 각 문자열을 개별적으로 소품으로 전달할 필요가 없습니다. 최상위 수준에서이를 변경하면 다시 렌더링이 트리거됩니다. 컨텍스트를 사용하는 것이 좋은 생각이 아니라고 생각합니다. 번역 파일에 대한 액세스 권한이있는 각 구성 요소는 실제로 imo를 덜 "벙어리"하고 이식 가능하게 만듭니다 (그리고 언어 변경시 앱을 다시 렌더링하는 것이 더 어렵습니다).
Dominic

1
실제로 facebook.github.io/react/docs/context.html 에 따르면 현재 언어를 공유하기 위해 컨텍스트를 사용하는 것은 합법적 인 사용 사례 중 하나입니다. 지금 시도하고있는 접근 방식은 특정 구성 요소 (아마도 일부 키를 기반으로 함)에 대한 문자열을 추출하는 논리를 처리하기 위해이 구성 요소와 Higher Order 구성 요소를 사용하는 것입니다
Antoine Jaussoin

1
Instant를 살펴볼 수도 있습니다 . 그들은이 문제를 프론트 엔드 ala Optimizely (로드하는 동안 DOM 변경)에서 처리함으로써 완전히 다른 방식으로이 문제를 처리합니다.
마르셀 Panse

1
나쁘지 않아! 그것은 실제로 완전히 다른 짐승입니다 (웹 사이트가 커지면 지불해야 할 서비스에 연결).하지만 나는 아이디어가 마음에 들며 빨리 실행 해야하는 작은 웹 사이트에 실제로 가치가 있습니다!
Antoine Jaussoin

4
또한, "그들"이라고 말하는 대신 Instant의 공동 창립자라고 언급 할 수도 있습니다. :)
Antoine Jaussoin

답변:


110

꽤 많은 솔루션을 시도한 후 잘 작동하고 React 0.14에 대한 관용적 솔루션이어야한다고 생각합니다 (즉, mixin을 사용하지 않지만 고차 구성 요소를 사용합니다) ( 편집 : 물론 React 15에서도 완벽하게 괜찮습니다! ).

따라서 여기에 솔루션은 하단 (개별 구성 요소)부터 시작됩니다.

구성 요소

컴포넌트가 (관습 적으로) 필요로하는 유일한 것은 stringsprops입니다. 컴포넌트에 필요한 다양한 문자열을 포함하는 객체 여야하지만 실제로 모양은 사용자에게 달려 있습니다.

기본 번역이 포함되어 있으므로 번역을 제공 할 필요없이 다른 곳에서 구성 요소를 사용할 수 있습니다 (이 예에서는 기본 언어 인 영어로 즉시 작동 함).

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 이 경우 컴포넌트를 래핑하고 몇 가지 추가 기능을 제공하는 Higher Order Component입니다 (이 구조는 이전 버전의 React 믹스 인을 대체합니다).

첫 번째 인수는 번역 파일에서 번역을 조회하는 데 사용되는 키입니다 (여기서는 구성 요소의 이름을 사용했지만 어떤 것이 든 가능). 두 번째 (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를 Flux와 유사한 구현으로 사용하고 있지만 다른 프레임 워크 / 패턴 / 라이브러리를 사용하여 쉽게 변환 할 수 있습니다.

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는 translate ()에 의해 래핑 될 필요가 없으며 분리 될 수 있으므로 strings자신의 수단으로 를 제공하려는 다른 사람이 재사용 할 수 있습니다 .

[편집 : 2016 년 3 월 31 일] : 최근 React & Redux로 구축 된 Retrospective Board (Agile Retrospectives 용)에서 작업했으며 다국어를 사용합니다. 많은 사람들이 댓글에서 실제 사례를 요청했기 때문에 다음과 같습니다.

여기에서 코드를 찾을 수 있습니다 : https://github.com/antoinejaussoin/retro-board/tree/master


이것은 멋진 솔루션입니다 .. 몇 달 후에도이 기능을 계속 사용하고 있는지 궁금하십니까? 이 온라인의 패턴에 대한 조언 방식에서 많은 조언을 찾지 못했습니다.
데이먼

2
나는 실제로 그것이 완벽하게 작동한다는 것을 알았습니다 (내 필요에 따라). 그것은 기본적으로 번역하지 않고 구성 요소 작품을 만들고, 번역은 구성 요소가 인식하지 않고 그 위에 온다
앙투안 Jaussoin

1
@ l.cetinsoy dangerouslySetInnerHTML소품을 사용할 수 있습니다 . 함축 된 의미를 염두에 두십시오 (입력을 수동으로 삭제). facebook.github.io/react/tips/dangerously-set-inner-html.html
Teodor Sandu를

6
react-intl을 시도하지 않은 이유가 있습니까?
SureshCS

1
이 솔루션을 정말 좋아합니다. 일관성과 시간 절약에 매우 유용하다는 점을 추가하고 싶습니다. 공통 문자열이있는 구성 요소가 많으면 변수를 활용하고 객체에 분산시킬 수 있습니다. 예const formStrings = { cancel, create, required }; export default { fooForm: { ...formStrings, foo: 'foo' }, barForm: { ...formStrings, bar: 'bar' } }
Huw Davies

18

내 경험상 가장 좋은 방법은 여러 가지 이유로 i18n redux 상태를 만들고 사용하는 것입니다.

1- 이렇게하면 데이터베이스, 로컬 파일 또는 EJS 또는 jade와 같은 템플릿 엔진에서 초기 값을 전달할 수 있습니다.

2- 사용자가 언어를 변경하면 UI를 새로 고치지 않고도 전체 응용 프로그램 언어를 변경할 수 있습니다.

3- 사용자가 언어를 변경하면 API, 로컬 파일 또는 상수에서 새 언어를 검색 할 수도 있습니다.

4- 시간대, 통화, 방향 (RTL / LTR) 및 사용 가능한 언어 목록과 같은 문자열로 다른 중요한 정보를 저장할 수도 있습니다.

5- 당신은 일반적인 redux 액션으로 언어 변경을 정의 할 수 있습니다

6- 백엔드 및 프런트 엔드 문자열을 한곳에 둘 수 있습니다. 예를 들어 제 경우에는 i18n-node 를 현지화에 사용하고 사용자가 UI 언어를 변경하면 일반 API 호출을 수행하고 백엔드에서는 그냥 반환합니다. 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- string-template 이렇게하면 카탈로그 문자열 사이에 값을 삽입 할 수 있습니다. 예를 들면 다음과 같습니다.

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)

삼- momentjs 는 가장 유명한 날짜 및 시간 npm 라이브러리입니다. moment를 번역 할 수 있지만 이미 내장 번역이 있습니다. 예를 들어 현재 상태 언어를 전달하면됩니다.

import moment from "moment";

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

업데이트 (2019 년 6 월 14 일)

현재 반응 컨텍스트 API (redux없이)를 사용하여 동일한 개념을 구현하는 많은 프레임 워크가 있습니다. 개인적으로 I18next를 추천 했습니다.


이 접근 방식이 두 개 이상의 언어에서 잘 작동합니까? 카탈로그 설정 고려
tempranova 17

아래로 투표했습니다. 이것은 질문에 대한 답이 아닙니다. OP는 i18n 라이브러리의 제안이나 비교가 아닌 아키텍처 아이디어를 요청했습니다.
TrungDQ 2017

9
REDUX 상태, 유 REDUX 이해가 안 보인다 나는 국제화 카탈로그를 제안
파리 드 자카 Alnamrouti

5

Antoine의 솔루션은 잘 작동하지만 몇 가지주의 사항이 있습니다.

  • 이미 Redux를 사용할 때 피하는 경향이있는 React 컨텍스트를 직접 사용합니다.
  • 클라이언트 측에서 런타임에 필요한 언어를 가져 오려는 경우 문제가 될 수있는 파일에서 직접 구문을 가져옵니다.
  • 가벼운 i18n 라이브러리를 사용하지 않지만 복수화 및 보간과 같은 편리한 번역 기능에 대한 액세스를 제공하지 않습니다.

이것이 우리가 Redux와 AirBNB의 Polyglot 위에 redux-polyglot 을 구축 한 이유 입니다. (저는 저자 중 한 명입니다)

다음을 제공합니다.

  • Redux 저장소에 언어 및 해당 메시지를 저장하는 감속기. 다음 중 하나를 통해 둘 다 제공 할 수 있습니다.
    • 특정 작업을 포착하고 현재 언어를 추론하고 관련 메시지를 가져 오거나 가져 오도록 구성 할 수있는 미들웨어입니다.
    • 직접 파견 setLanguage(lang, messages)
  • 4 개의 메소드를 노출 getP(state)하는 P객체 를 검색 하는 선택기 :
    • t(key): 원래 다국어 T 함수
    • 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
번역 할 훨씬 더 나은 원래 문구. _()예를 들어 모든 문자열을 가져 오기 위해 함수에 대한 모든 구성 요소를 구문 분석하는 도구를 만듭니다 . 따라서 언어 파일에서 더 쉽게 번역하고 미친 변수를 엉망으로 만들 수 없습니다. 경우에 따라 랜딩 페이지는 레이아웃의 특정 부분을 다르게 표시해야합니다. 따라서 기본과 다른 가능한 선택을 선택하는 방법에 대한 스마트 기능도 사용할 수 있어야합니다.
Roman M. Koss

안녕하세요 @Jalil, 미들웨어에 대한 완전한 예가 있습니까?
ArkadyB

안녕하세요 @ArkadyB, 오픈 소스가 아닌 여러 프로젝트의 프로덕션에 사용합니다. README 모듈에서 더 많은 정보를 찾을 수 있습니다. npmjs.com/package/redux-polyglot 사용하는 데 질문 / 어려움이 있습니까?
Jalil

이것과 polyglot.js의 주요 문제는 PO 파일 위에 빌드하는 것이 아니라 바퀴를 완전히 재창조하고 있다는 것입니다. 이 대체 라이브러리는 유망 보입니다. npmjs.com/package/redux-i18n . 나는 그것이 많이 다르지 않다고 생각하지 않습니다. 단지 PO 파일과 변환 할 추가 레이어를 제공하는 것입니다.
icc97

2

이에 대한 내 연구에서 JavaScript, ICUgettext 에서 i18n에 사용되는 두 가지 주요 접근 방식이있는 것으로 보입니다 .

저는 gettext 만 사용했기 때문에 편견이 있습니다.

나를 놀라게하는 것은 지원이 얼마나 열악한 지입니다. 저는 CakePHP 또는 WordPress와 같은 PHP 세계에서 왔습니다. 이 두 가지 상황 모두에서 모든 현을 단순히 둘러싸는 것이 기본 표준입니다.__('') 다음 줄 아래로 내려 가면 PO 파일을 사용하여 번역을 매우 쉽게 얻는 .

gettext

문자열 형식화에 대한 sprintf에 익숙해지면 수천 개의 다른 기관에서 PO 파일을 쉽게 번역 할 수 있습니다.

두 가지 인기있는 옵션이 있습니다.

  1. i18next ,이 arkency.com 블로그 게시물에 설명 된 사용법
  2. Jed , sentry.io 게시물에 설명 된 사용법 및이 React + Redux 게시물에 ,

둘 다 gettext 스타일 지원, 문자열의 sprintf 스타일 형식화 및 PO 파일로 가져 오기 / 내보내기가 있습니다.

i18next에는 자체적으로 개발 된 React 확장 이 있습니다. Jed는 그렇지 않습니다. Sentry.io는 Jed와 React의 사용자 정의 통합을 사용하는 것으로 보입니다. 그만큼 + 돌아 오는 포스트 반응 , 사용 제안

도구 : jed + po2json + jsxgettext

그러나 Jed는 좀 더 gettext에 초점을 맞춘 구현처럼 보입니다. 즉, i18next가 옵션으로 제공하는 의도를 표현한 것입니다.

ICU

이것은 예를 들어 성별을 다루는 것과 같은 번역과 관련된 가장자리 사례를 더 많이 지원합니다. 번역 할 더 복잡한 언어가 있다면 이것의 이점을 보게 될 것입니다.

이에 대한 인기있는 옵션은 messageformat.js 입니다. 이 sentry.io 블로그 자습서 에서 간략하게 논의했습니다 . messageformat.js는 실제로 Jed를 작성한 사람이 개발했습니다. 그는 ICU를 사용하는 것에 대해 상당히 강력한 주장을합니다 .

Jed는 내 생각에 완전한 기능입니다. 버그를 고쳐서 기쁘지만 일반적으로 라이브러리에 더 많은 것을 추가하는 데는 관심이 없습니다.

나는 또한 messageformat.js를 유지합니다. 특별히 gettext 구현이 필요하지 않은 경우 복수 / 성별을 더 잘 지원하고 로케일 데이터가 내장되어 있으므로 대신 MessageFormat을 사용하는 것이 좋습니다.

대략적인 비교

sprintf를 사용한 gettext :

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

아래로 투표했습니다. 이것은 질문에 대한 답이 아닙니다. OP는 i18n 라이브러리의 제안이나 비교가 아닌 아키텍처 아이디어를 요청했습니다.
TrungDQ

@TrungDQ 이것은 OP가 질문 한 것입니다. "제 질문은 순수하게 기술적 인 것이 아니라 아키텍처 와 사람들이 실제로이 문제를 해결하기 위해 프로덕션 에서 사용하는 패턴에 관한 것입니다 ." . 이들은 생산에 사용되는 두 가지 패턴입니다.
icc97

제 생각에이 답변은 제가 찾고있는 정보를 제공하지 않습니다. 제공하신 정보는 도움이되지만 다른 질문이있을 수 있습니다. 정답이 상단에 표시되도록 내 반대표를 제공하고 싶습니다.
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>

다음에 대한 샘플이 제공됩니다.

  • 웹팩
  • CRA
  • expo.js
  • next.js
  • 동화책 통합
  • 야단법석
  • dat
  • ...

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

또한 개발 중 및 나중에 번역사를 위해 워크 플로를 고려해야합니다.-> https://www.youtube.com/watch?v=9NOzJhgmyQE


이것은 질문에 대한 답이 아닙니다. OP는 i18n 라이브러리의 제안이나 비교가 아닌 아키텍처 아이디어를 요청했습니다.
TrungDQ 2017

@TrungDQ는 내 대답에 대한 귀하의 의견과 마찬가지로 OP는 프로덕션에 사용되는 현재 솔루션을 요청했습니다. 그러나 나는 2 월 에 나의 대답 에서 i18next를 제안했다.
icc97

0

create-react-app을 사용하여 간단한 솔루션을 제안하고 싶습니다 .

응용 프로그램은 모든 언어에 대해 개별적으로 빌드되므로 전체 번역 논리가 응용 프로그램에서 제거됩니다.

웹 서버는 Accept-Language 헤더 에 따라 자동으로 올바른 언어를 제공 하거나 쿠키 를 설정하여 수동으로 제공합니다. .

대부분 언어를 한 번 이상 변경하지 않습니다.

스타일, 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",

그게 다야!

또한 내 원래 답변에는 각 번역에 대해 단일 json 파일로 더 모 놀리 식 접근 방식이 포함되었습니다.

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

컴파일 타임에만 작동하지 않습니까? 사용자가 즉석에서 언어를 변경할 수있는 기능이 없습니까? 그러면 다른 사용 사례가됩니다.
Antoine Jaussoin

앱은 필요한 모든 언어로 컴파일됩니다. 웹 서버는 "Accept-Language"헤더에 따라 또는 사용자가 즉석에서 설정 한 쿠키에 따라 올바른 버전을 자동으로 제공합니다. 이렇게함으로써 전체 번역 로직을 앱 밖으로 이동할 수 있습니다.
Igor Sukharev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.