Yuki Takei 5 лет назад
Родитель
Сommit
67dbbe4ad6

+ 11 - 12
src/client/js/components/Admin/App/AppSetting.jsx

@@ -3,10 +3,11 @@ import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import loggerFactory from '@alias/logger';
 
+import { localeMetadatas } from '../../../util/i18n';
+
 import { withUnstatedContainers } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '../../../util/apiNotification';
 
-import AppContainer from '../../../services/AppContainer';
 import AdminAppContainer from '../../../services/AdminAppContainer';
 import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
@@ -34,9 +35,8 @@ class AppSetting extends React.Component {
   }
 
   render() {
-    const { t, adminAppContainer, appContainer } = this.props;
-    const locales = appContainer.locales;
-    const languages = Object.keys(locales);
+    const { t, adminAppContainer } = this.props;
+
     return (
       <React.Fragment>
         <div className="form-group row">
@@ -83,20 +83,20 @@ class AppSetting extends React.Component {
           </label>
           <div className="col-md-6">
             {
-              languages.map(lan => (
-                <div key={lan} className="custom-control custom-radio custom-control-inline">
+              localeMetadatas.map(meta => (
+                <div key={meta.id} className="custom-control custom-radio custom-control-inline">
                   <input
                     type="radio"
-                    id={`radioLang${lan}`}
+                    id={`radioLang${meta.id}`}
                     className="custom-control-input"
                     name="globalLang"
-                    value={lan}
-                    checked={adminAppContainer.state.globalLang === lan}
+                    value={meta.id}
+                    checked={adminAppContainer.state.globalLang === meta.id}
                     onChange={(e) => {
                       adminAppContainer.changeGlobalLang(e.target.value);
                     }}
                   />
-                  <label className="custom-control-label" htmlFor={`radioLang${lan}`}>{locales[lan].meta.name}</label>
+                  <label className="custom-control-label" htmlFor={`radioLang${meta.id}`}>{meta.name}</label>
                 </div>
               ))
             }
@@ -145,11 +145,10 @@ class AppSetting extends React.Component {
 /**
  * Wrapper component for using unstated
  */
-const AppSettingWrapper = withUnstatedContainers(AppSetting, [AppContainer, AdminAppContainer]);
+const AppSettingWrapper = withUnstatedContainers(AppSetting, [AdminAppContainer]);
 
 AppSetting.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminAppContainer: PropTypes.instanceOf(AdminAppContainer).isRequired,
 };
 

+ 10 - 11
src/client/js/components/InstallerForm.jsx

@@ -4,6 +4,8 @@ import PropTypes from 'prop-types';
 import i18next from 'i18next';
 import { withTranslation } from 'react-i18next';
 
+import { localeMetadatas } from '../util/i18n';
+
 class InstallerForm extends React.Component {
 
   constructor(props) {
@@ -44,9 +46,6 @@ class InstallerForm extends React.Component {
       : <span><i className="icon-fw icon-ban" />{ this.props.t('installer.unavaliable_user_id') }</span>;
 
     const checkedBtn = this.state.checkedBtn;
-    const { i18n } = this.props;
-    const locales = i18n.options.resources;
-    const languages = Object.keys(locales);
 
     return (
       <div className={`login-dialog p-3 mx-auto${hasErrorClass}`}>
@@ -62,19 +61,19 @@ class InstallerForm extends React.Component {
           <form role="form" action="/installer" method="post" id="register-form" className="col-md-12">
             <div className="form-group text-center">
               {
-                languages.map(lan => (
-                  <div key={lan} className="custom-control custom-radio custom-control-inline">
+                localeMetadatas.map(meta => (
+                  <div key={meta.id} className="custom-control custom-radio custom-control-inline">
                     <input
                       type="radio"
                       className="custom-control-input"
-                      id={`register-form-check-${lan}`}
+                      id={`register-form-check-${meta.id}`}
                       name="registerForm[app:globalLang]"
-                      value={lan}
-                      checked={checkedBtn === lan}
-                      onChange={(e) => { if (e.target.checked) { this.changeLanguage(lan) } }}
+                      value={meta.id}
+                      checked={checkedBtn === meta.id}
+                      onChange={(e) => { if (e.target.checked) { this.changeLanguage(meta.id) } }}
                     />
-                    <label className="custom-control-label" htmlFor={`register-form-check-${lan}`}>
-                      {locales[lan].meta.name}
+                    <label className="custom-control-label" htmlFor={`register-form-check-${meta.id}`}>
+                      {meta.name}
                     </label>
                   </div>
                 ))

+ 11 - 13
src/client/js/components/Me/BasicInfoSettings.jsx

@@ -3,15 +3,16 @@ import React, { Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
+import { localeMetadatas } from '../../util/i18n';
+
 import { toastSuccess, toastError } from '../../util/apiNotification';
 import { withUnstatedContainers } from '../UnstatedUtils';
 
-import AppContainer from '../../services/AppContainer';
 import PersonalContainer from '../../services/PersonalContainer';
 
 class BasicInfoSettings extends React.Component {
 
-  constructor(appContainer) {
+  constructor() {
     super();
 
     this.onClickSubmit = this.onClickSubmit.bind(this);
@@ -39,10 +40,8 @@ class BasicInfoSettings extends React.Component {
   }
 
   render() {
-    const { t, personalContainer, appContainer } = this.props;
+    const { t, personalContainer } = this.props;
     const { registrationWhiteList } = personalContainer.state;
-    const locales = appContainer.locales;
-    const languages = Object.keys(locales);
 
     return (
       <Fragment>
@@ -113,17 +112,17 @@ class BasicInfoSettings extends React.Component {
           <label className="text-left text-md-right col-md-3 col-form-label">{t('Language')}</label>
           <div className="col-md-6">
             {
-              languages.map(lan => (
-                <div key={lan} className="custom-control custom-radio custom-control-inline">
+              localeMetadatas.map(meta => (
+                <div key={meta.id} className="custom-control custom-radio custom-control-inline">
                   <input
                     type="radio"
-                    id={`radioLang${lan}`}
+                    id={`radioLang${meta.id}`}
                     className="custom-control-input"
                     name="userForm[lang]"
-                    checked={personalContainer.state.lang === lan}
-                    onChange={() => { personalContainer.changeLang(lan) }}
+                    checked={personalContainer.state.lang === meta.id}
+                    onChange={() => { personalContainer.changeLang(meta.id) }}
                   />
-                  <label className="custom-control-label" htmlFor={`radioLang${lan}`}>{locales[lan].meta.name}</label>
+                  <label className="custom-control-label" htmlFor={`radioLang${meta.id}`}>{meta.name}</label>
                 </div>
               ))
             }
@@ -144,11 +143,10 @@ class BasicInfoSettings extends React.Component {
 
 }
 
-const BasicInfoSettingsWrapper = withUnstatedContainers(BasicInfoSettings, [AppContainer, PersonalContainer]);
+const BasicInfoSettingsWrapper = withUnstatedContainers(BasicInfoSettings, [PersonalContainer]);
 
 BasicInfoSettings.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   personalContainer: PropTypes.instanceOf(PersonalContainer).isRequired,
 };
 

+ 1 - 1
src/client/js/nologin.jsx

@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom';
 import { Provider } from 'unstated';
 import { I18nextProvider } from 'react-i18next';
 
-import i18nFactory from './util/i18n';
+import { i18nFactory } from './util/i18n';
 
 import AppContainer from './services/AppContainer';
 

+ 1 - 2
src/client/js/services/AppContainer.js

@@ -14,7 +14,7 @@ import {
 } from '../util/color-scheme';
 import Apiv1ErrorHandler from '../util/apiv1ErrorHandler';
 
-import i18nFactory from '../util/i18n';
+import { i18nFactory } from '../util/i18n';
 import apiv3ErrorHandler from '../util/apiv3ErrorHandler';
 
 /**
@@ -49,7 +49,6 @@ export default class AppContainer extends Container {
 
     const userLocaleId = this.currentUser.lang;
     this.i18n = i18nFactory(userLocaleId);
-    this.locales = this.i18n.options.resources;
 
     this.containerInstances = {};
     this.componentInstances = {};

+ 6 - 3
src/client/js/util/i18n.js

@@ -2,9 +2,12 @@ import i18n from 'i18next';
 import LanguageDetector from 'i18next-browser-languagedetector';
 import { initReactI18next } from 'react-i18next';
 
-import resources from '@root/resource/locales';
+import locales from '@root/resource/locales';
 
-export default (userLocaleId) => {
+// extract metadata list from 'resource/locales/${locale}/meta.json'
+export const localeMetadatas = Object.values(locales).map(locale => locale.meta);
+
+export const i18nFactory = (userLocaleId) => {
   // setup LanguageDetector
   const langDetector = new LanguageDetector();
   langDetector.addDetector({
@@ -21,7 +24,7 @@ export default (userLocaleId) => {
     .use(initReactI18next) // if not using I18nextProvider
     .init({
       debug: (process.env.NODE_ENV !== 'production'),
-      resources,
+      resources: locales,
       load: 'currentOnly',
 
       fallbackLng: 'en_US',