Skip to content

Commit

Permalink
feat(admin): add i18n support, zh-cn and en-us now
Browse files Browse the repository at this point in the history
  • Loading branch information
lizheming committed Feb 8, 2021
1 parent dafd706 commit 3f49034
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 86 deletions.
3 changes: 3 additions & 0 deletions packages/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@
"css-loader": "^5.0.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^4.5.0",
"i18next": "^19.8.7",
"i18next-browser-languagedetector": "^6.0.1",
"marked": "^1.2.3",
"md5": "^2.3.0",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-i18next": "^11.8.5",
"react-redux": "^7.2.2",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
Expand Down
8 changes: 5 additions & 3 deletions packages/admin/src/components/Header.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import { Link } from '@reach/router';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';

export default function() {
const dispatch = useDispatch();
const user = useSelector(state => state.user);
const { t } = useTranslation();

const onLogout = function(e) {
e.preventDefault();
Expand All @@ -19,11 +21,11 @@ export default function() {
<nav id="typecho-nav-list">
<ul className="root">
<li className="parent">
<Link to={basepath + '/ui'}>管理</Link>
<Link to={basepath + '/ui'}>{t('management')}</Link>
</li>
<ul className="child">
<li className="last">
<Link to={basepath + '/ui'}>评论</Link>
<Link to={basepath + '/ui'}>{t('comment')}</Link>
</li>
</ul>
</ul>
Expand All @@ -32,7 +34,7 @@ export default function() {

<div className="operate">
<Link to={basepath + '/ui/profile'} className="author">{user.display_name}</Link>
<a className="exit" href="#" onClick={onLogout}>登出</a>
<a className="exit" href="#" onClick={onLogout}>{t('logout')}</a>
</div>
</div>
)
Expand Down
10 changes: 5 additions & 5 deletions packages/admin/src/components/Paginator.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ export default function({current, total, onChange}) {
<ul className="typecho-pager">
{current > 1 ? (
<li className="prev">
<a href="javascript:void(0)" onClick={_ => onChange(current - 1)}>«</a>
<a href="#" onClick={_ => onChange(current - 1)}>«</a>
</li>
) : null}
{current > 4 ? (
<>
<li><a href="javascript:void(0)" onClick={_ => onChange(1)}>1</a></li>
<li><a href="#" onClick={_ => onChange(1)}>1</a></li>
<li><span>...</span></li>
</>
) : null}
Expand All @@ -29,17 +29,17 @@ export default function({current, total, onChange}) {
current + 3
].filter(page => page > 0 && page <= total).map(page => (
<li key={page} className={cls({current: page === current})}>
<a href="javascript:void(0)" onClick={_ => onChange(page)}>{page}</a>
<a href="#" onClick={_ => onChange(page)}>{page}</a>
</li>
))}
{current < total - 3 ? (
<>
<li><span>...</span></li>
<li><a href="javascript:void(0)" onClick={_ => onChange(total)}>{total}</a></li>
<li><a href="#" onClick={_ => onChange(total)}>{total}</a></li>
</>
) : null}
{current < total ? (
<li className="next"><a href="javascript:void(0)" onClick={_ => onChange(current + 1)}>»</a></li>
<li className="next"><a href="#" onClick={_ => onChange(current + 1)}>»</a></li>
) : null}
</ul>
)
Expand Down
28 changes: 28 additions & 0 deletions packages/admin/src/i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

import langs from './locales';


i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
// we init with resources
resources: langs,
fallbackLng: "zh-CN",
debug: true,

// have a common namespace used around the full app
ns: ["translations"],
defaultNS: "translations",

keySeparator: false, // we use content as keys

interpolation: {
escapeValue: false
}
});

export default i18n;
2 changes: 2 additions & 0 deletions packages/admin/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import ReactDOM from 'react-dom';
import App from './App';
import { store } from './store';

import './i18n';

import './style/normalize.css';
import './style/grid.css';
import './style/style.css';
Expand Down
58 changes: 58 additions & 0 deletions packages/admin/src/locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"management": "Management",
"comment": "Comment",
"login": "Login",
"logout": "Logout",
"register": "Register",
"email": "Email",
"password": "Password",
"remember me": "Remember me",
"back to home": "Back to Home",
"please input email": "Please input email!",
"please input password": "Please input password!",
"email or password error": "Email or Password error!",
"nickname": "Nickname",
"website": "Personal Website",
"password again": "Password Again",
"register.login": "Login",
"nickname illegal": "Nickname Illegal!",
"passwords don't match": "Passwords don't match",
"register error! try again later": "Register error! Try again later!",
"setting": "Setting",
"profile": "Profile",
"go to gravatar to change avatar": "Go to Gravatar to change avatar",
"homepage": "Homepage",
"homepage tips": "Current users' homepage. It must be start with <1>http:\/\/<\/1> or <1>https:\/\/<\/1>.",
"update my profile": "Update my profile",
"connect to social account": "Connect to Social Account",
"change password": "Change Password",
"update password": "Update password",
"password tips": "It's recommended to use a mixed style of special characters, letters and numbers to increase system security.",
"password again tips": "Please confirm your password, consistent with the password entered above.",
"nickname and homepage are required": "Both nickname and personal homepage are required fields.",
"all": "All",
"mine": "Mine",
"approved": "Approved",
"approved button": "Approved",
"waiting": "Waiting",
"spam": "Spam",
"mark as spam": "Mark as Spam",
"edit": "Edit",
"reply": "Reply",
"delete": "Delete",
"delete one confirm": "Are you sure you want to delete {{nick}}'s comment?",
"delete multiple confirm": "Are you sure you want to delete these comments?",
"manage comments": "Manage Comments",
"select all": "Select All",
"action": "Action",
"selected items": "Selected Action",
"please input keywords": "Please input keywords",
"filter": "Filter",
"author": "Author",
"content": "Content",
"username": "Username",
"submit": "Submit",
"cancel": "Cancel",
"at": "At",
"get userinfo failed": "Get userinfo failed!"
}
12 changes: 12 additions & 0 deletions packages/admin/src/locales/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import en from './en.json';
import zhCN from './zh-CN.json';

export default {
"zh-cn": { translations: zhCN },
"zh-CN": { translations: zhCN },
"en": { translations: en },
"en-US": { translations: en },
"zh-TW": { translations: en },
"jp": { translations: en },
"jp-JP": { translations: en }
};
58 changes: 58 additions & 0 deletions packages/admin/src/locales/zh-CN.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"management": "管理",
"comment": "评论",
"login": "登录",
"logout": "登出",
"register": "用户注册",
"email": "邮箱",
"password": "密码",
"remember me": "下次自动登录",
"back to home": "返回首页",
"please input email": "请输入邮箱",
"please input password": "请输入密码",
"email or password error": "账号密码错误",
"nickname": "昵称",
"website": "个人网站",
"password again": "再次输入密码",
"register.login": "用户登录",
"nickname illegal": "请输入正确的昵称",
"passwords don't match": "两次密码不一致",
"register error! try again later": "注册失败,请稍后再试!",
"setting": "个人设置",
"profile": "个人资料",
"go to gravatar to change avatar": "在 Gravatar 上修改头像",
"homepage": "个人主页地址",
"homepage tips": "此用户的个人主页地址, 请用 <1>http:\/\/</1> 或 <1>https:\/\/</1> 开头.",
"update my profile": "更新我的档案",
"connect to social account": "账号绑定",
"change password": "密码修改",
"update password": "更新密码",
"password tips": "为此用户分配一个密码.<br />建议使用特殊字符与字母、数字的混编样式,以增加系统安全性.",
"password again tips": "请确认你的密码, 与上面输入的密码保持一致.",
"nickname and homepage are required": "昵称和个人主页都是必填字段",
"all": "所有",
"mine": "我的",
"approved": "已通过",
"approved button": "通过",
"waiting": "待审核",
"spam": "垃圾",
"mark as spam": "标记垃圾",
"edit": "编辑",
"reply": "回复",
"delete": "删除",
"delete one confirm": "你确认要删除{{nick}}的评论吗?",
"delete multiple confirm": "你确认要删除这些评论吗?",
"manage comments": "管理评论",
"select all": "全选",
"action": "操作",
"selected items": "选中项",
"please input keywords": "请输入关键字",
"filter": "筛选",
"author": "作者",
"content": "内容",
"username": "用户名",
"submit": "提交",
"cancel": "取消",
"at": "",
"get userinfo failed": "获取用户信息失败"
}
22 changes: 12 additions & 10 deletions packages/admin/src/pages/login/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { useEffect, useState } from 'react';
import { Link, navigate } from '@reach/router';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';

import * as Icons from '../../components/icon';

export default function() {
const { t } = useTranslation();
const dispatch = useDispatch();
const user = useSelector(state => state.user);
const [error, setError] = useState(false);
Expand All @@ -28,17 +30,17 @@ export default function() {
const password = e.target.password.value;
const remember = e.target.remember.checked;
if(!email) {
return setError('请输入邮箱');
return setError(t('please input email'));
}
if(!password) {
return setError('请输入密码');
return setError(t('please input password'));
}

try {
await dispatch.user.login({email, password, remember});
navigate('/ui', {replace: true});
} catch(e) {
setError('账号密码错误');
setError(t('email or password error'));
}
};

Expand Down Expand Up @@ -67,19 +69,19 @@ export default function() {
{/* <h1><a href="http://waline.js.org" className="i-logo">Waline</a></h1> */}
<form method="post" name="login" role="form" onSubmit={onSubmit}>
<p>
<label htmlFor="email" className="sr-only">邮箱</label>
<input type="text" id="email" name="email" placeholder="邮箱" className="text-l w-100" />
<label htmlFor="email" className="sr-only">{t('email')}</label>
<input type="text" id="email" name="email" placeholder={t('email')} className="text-l w-100" />
</p>
<p>
<label htmlFor="password" className="sr-only">密码</label>
<input type="password" id="password" name="password" className="text-l w-100" placeholder="密码" />
<label htmlFor="password" className="sr-only">{t('password')}</label>
<input type="password" id="password" name="password" className="text-l w-100" placeholder={t('password')} />
</p>
<p className="submit">
<button type="submit" className="btn btn-l w-100 primary">登录</button>
<button type="submit" className="btn btn-l w-100 primary">{t('login')}</button>
</p>
<p>
<label htmlFor="remember">
<input type="checkbox" name="remember" className="checkbox" id="remember"/> 下次自动登录
<input type="checkbox" name="remember" className="checkbox" id="remember"/> {t('remember me')}
</label>
</p>
</form>
Expand All @@ -92,7 +94,7 @@ export default function() {
</div>

<p className="more-link">
<Link to="/ui">返回首页</Link><Link to="/ui/register">用户注册</Link>
<Link to="/ui">{t('back to home')}</Link><Link to="/ui/register">{t('register')}</Link>
</p>
</div>
</div>
Expand Down

0 comments on commit 3f49034

Please sign in to comment.