Skip to content

Commit

Permalink
完善 hkuserver 多国语言
Browse files Browse the repository at this point in the history
  • Loading branch information
fasiondog committed May 2, 2021
1 parent 4af29a5 commit 754353e
Show file tree
Hide file tree
Showing 18 changed files with 153 additions and 87 deletions.
9 changes: 5 additions & 4 deletions hikyuu_cpp/hikyuu_server/common/mo.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
/*
* Copyright(C) 2021 hikyuu.org
*
* Create on: 2021-05-01
* Create on: 2021-05-02
* Author: fasiondog
*/

#include "mo.h"

namespace hku {

moFileLib::moFileReader g_moFR;
std::unordered_map<std::string, moFileLib::moFileReader> MOHelper::ms_dict;

void mo_init(const char *filename) {
g_moFR.ReadFile(filename);
void MOHelper::init() {
ms_dict["zh_cn"] = moFileLib::moFileReader();
ms_dict["zh_cn"].ReadFile("i8n/zh_CN.mo");
}

} // namespace hku
29 changes: 22 additions & 7 deletions hikyuu_cpp/hikyuu_server/common/mo.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,33 @@

#pragma once

#include <string_view>
#include <unordered_map>
#include "moFileReader.hpp"

// 多国语言支持
#define _(S) hku::g_moFR.Lookup(S)
#define _L(S) hku::moFR.Lookup(S)
#define _LC(ctx, str) hku::moFR.LookupWithContext(ctx, str)
#if defined(_MSC_VER)
// moFileReader.hpp 最后打开了4251告警,这里关闭
#pragma warning(disable : 4251)
#endif /* _MSC_VER */

namespace hku {

extern moFileLib::moFileReader g_moFR;
class MOHelper {
public:
static void init();

// 初始化读取mo文件
void mo_init(const char *filename);
static std::string translate(const std::string &lang, const char *id) {
auto iter = ms_dict.find(lang);
return iter != ms_dict.end() ? ms_dict[lang].Lookup(id) : std::string(id);
}

static std::string translate(const std::string &lang, const char *ctx, const char *id) {
auto iter = ms_dict.find(lang);
return iter != ms_dict.end() ? ms_dict[lang].LookupWithContext(ctx, id) : std::string(id);
}

private:
static std::unordered_map<std::string, moFileLib::moFileReader> ms_dict;
};

} // namespace hku
4 changes: 3 additions & 1 deletion hikyuu_cpp/hikyuu_server/extract_pot.bat
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
xgettext -k_ -k"_LC:1c,2" -k"_LC:1c,2" -s -c --package-name=hikyuu -f po/POTFILES.in -o po/hikyuu.pot
; 实际不需要使用该命令,因为不能自动更新;实际直接使用 poedit 打开 i8n/zh_CN.po 进行更新
; 此处保留,用于 poedit 设置关键字时参考
xgettext -k_tr -k"_ctr:1c,2" -s -c --package-name=hikyuu -f i8n/POTFILES.in -o i8n/hikyuu.pot
17 changes: 15 additions & 2 deletions hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Author: fasiondog
*/

#include <hikyuu/utilities/arithmetic.h>
#include "url.h"
#include "HttpHandle.h"

Expand Down Expand Up @@ -109,9 +110,9 @@ void HttpHandle::unknown_error(const std::string& errmsg) {
}
}

std::string HttpHandle::getReqHeader(const std::string& name) {
std::string HttpHandle::getReqHeader(const char* name) const {
std::string result;
const char* head = nng_http_req_get_header(m_nng_req, name.c_str());
const char* head = nng_http_req_get_header(m_nng_req, name);
if (head) {
result = std::string(head);
}
Expand Down Expand Up @@ -192,4 +193,16 @@ bool HttpHandle::getQueryParams(QueryParams& query_params) {
return query_params.size() != 0;
}

std::string HttpHandle::getLanguage() const {
std::string lang = getReqHeader("Accept-Language");
auto pos = lang.find_first_of(',');
if (pos != std::string::npos) {
lang = lang.substr(0, pos);
}
if (!lang.empty()) {
to_lower(lang);
}
return lang;
}

} // namespace hku
40 changes: 36 additions & 4 deletions hikyuu_cpp/hikyuu_server/http/HttpHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
#include <functional>

#include <nlohmann/json.hpp>

#include "HttpError.h"
#include "../common/log.h"
#include "common/mo.h"
#include "common/log.h"

using json = nlohmann::json; // 不保持插入排序
using ordered_json = nlohmann::ordered_json; // 保持插入排序
Expand Down Expand Up @@ -60,9 +60,18 @@ class HttpHandle {
/**
* 获取请求头部信息
* @param name 头部信息名称
* @return 如果获取不到将返回 NULL
* @return 如果获取不到将返回""
*/
std::string getReqHeader(const std::string &name);
std::string getReqHeader(const char *name) const;

/**
* 获取请求头部信息
* @param name 头部信息名称
* @return 如果获取不到将返回""
*/
std::string getReqHeader(const std::string &name) const {
return getReqHeader(name.c_str());
}

/**
* 获取请求数据
Expand Down Expand Up @@ -116,6 +125,29 @@ class HttpHandle {
setResData(data.dump());
}

/**
* 从 Accept-Language 获取第一个语言类型
* @note 非严格 html 协议,仅返回排在最前面的语言类型
*/
std::string getLanguage() const;

/**
* 多语言翻译
* @param msgid 待翻译的字符串
*/
std::string _tr(const char *msgid) const {
return MOHelper::translate(getLanguage(), msgid);
}

/**
* 多语言翻译
* @param ctx 翻译上下文
* @param msgid 待翻译的字符串
*/
std::string _ctr(const char *ctx, const char *msgid) {
return MOHelper::translate(getLanguage(), ctx, msgid);
}

void operator()();

private:
Expand Down
2 changes: 1 addition & 1 deletion hikyuu_cpp/hikyuu_server/http/HttpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void HttpServer::start() {

#if defined(_WIN32)
// Windows 下设置控制台程序输出代码页为 UTF8
auto g_old_cp = GetConsoleOutputCP();
g_old_cp = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8);
#endif

Expand Down
3 changes: 3 additions & 0 deletions hikyuu_cpp/hikyuu_server/i8n/POTFILES.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
service/filter.cpp
service/user/SignHandle.h
service/user/UserHandle.h
Binary file modified hikyuu_cpp/hikyuu_server/i8n/zh_CN.mo
Binary file not shown.
52 changes: 52 additions & 0 deletions hikyuu_cpp/hikyuu_server/i8n/zh_CN.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
msgid ""
msgstr ""
"Project-Id-Version: Hikyuu\n"
"POT-Creation-Date: 2021-05-03 01:44+0800\n"
"PO-Revision-Date: 2021-05-03 01:44+0800\n"
"Last-Translator: \n"
"Language-Team: hikyuu.org\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.4.3\n"
"X-Poedit-Basepath: ..\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: _tr;_ctr:1c,2\n"
"X-Poedit-SearchPath-0: .\n"

#: service/filter.cpp:30
msgctxt "authorize"
msgid "Miss token"
msgstr "缺失令牌"

#: service/filter.cpp:32
msgctxt "authorize"
msgid "Invalid token"
msgstr "无效令牌"

#: service/filter.cpp:66
msgctxt "authorize"
msgid "token is expired"
msgstr "令牌过期"

#: service/user/SignHandle.h:35 service/user/UserHandle.h:42
msgctxt "user"
msgid "Duplicate user name"
msgstr "用户名重复"

#: service/user/SignHandle.h:62
msgctxt "user"
msgid "User does not exist"
msgstr "用户不存在"

#: service/user/SignHandle.h:64
msgctxt "user"
msgid "Wrong password"
msgstr "密码错误"

#: service/user/UserHandle.h:63
msgctxt "user"
msgid "No operation permission"
msgstr "没有操作权限"
13 changes: 2 additions & 11 deletions hikyuu_cpp/hikyuu_server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,15 @@
#include "service/assist/AssistService.h"
#include "service/trade/TradeService.h"

#if defined(_WIN32) || defined(_WIN64)
#include <Winnls.h>
#pragma comment(lib, "Kernel32.lib")
#endif

using namespace hku;

#define HKU_SERVICE_API(name) "/hku/" #name "/v1"

int main(int argc, char* argv[]) {
init_server_logger();

#if defined(_WIN32) || defined(_WIN64)
LANGID lid = GetSystemDefaultLangID();
if (lid == 0x0804) {
mo_init("i8n/zh_CN.mo");
}
#endif
// 初始化多语言支持
MOHelper::init();

LOG_INFO("start server ... You can press Ctrl-C stop");

Expand Down
1 change: 0 additions & 1 deletion hikyuu_cpp/hikyuu_server/po/POTFILES.in

This file was deleted.

22 changes: 0 additions & 22 deletions hikyuu_cpp/hikyuu_server/po/hikyuu.pot

This file was deleted.

23 changes: 0 additions & 23 deletions hikyuu_cpp/hikyuu_server/po/zh_CN.po

This file was deleted.

2 changes: 1 addition & 1 deletion hikyuu_cpp/hikyuu_server/service/RestHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#pragma once

#include <stdlib.h>
#include "common/mo.h"
#include "http/HttpHandle.h"
#include "db/db.h" // 这里统一引入
#include "RestErrorCode.h"
Expand All @@ -32,6 +31,7 @@ class NoAuthRestHandle : public HttpHandle {
virtual void after_run() override {
// 强制关闭连接,即仅有短连接
// nng_http_res_set_status(m_nng_res, NNG_HTTP_STATUS_OK);
std::string lang = getLanguage();
setResData(res);
}

Expand Down
8 changes: 4 additions & 4 deletions hikyuu_cpp/hikyuu_server/service/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ std::string createToken(uint64_t user_id) {
}

struct TokenExpiredException : public hku::exception {
TokenExpiredException() : hku::exception("token is expired") {}
TokenExpiredException(const std::string &msg) : hku::exception(msg) {}
};

void AuthorizeFilter(HttpHandle *handle) {
std::string token = handle->getReqHeader("hku_token");
HTTP_CHECK(!token.empty(), RestErrorCode::MISS_TOKEN, "Miss token");
HTTP_CHECK(!token.empty(), RestErrorCode::MISS_TOKEN, handle->_ctr("authorize", "Miss token"));

const char *errmsg = "Invalid token";
std::string errmsg = handle->_ctr("authorize", "Invalid token");
if (!TokenCache::have(token)) {
TokenModel token_record;
DB::getConnect()->load(token_record, fmt::format(R"(token="{}")", token));
Expand Down Expand Up @@ -63,7 +63,7 @@ void AuthorizeFilter(HttpHandle *handle) {
con->exec(fmt::format(R"(delete from {} where token="{}")",
TokenModel::getTableName(), token));
}
throw TokenExpiredException();
throw TokenExpiredException(handle->_ctr("authorize", "token is expired"));
}

RestHandle *rest_handle = dynamic_cast<RestHandle *>(handle);
Expand Down
8 changes: 5 additions & 3 deletions hikyuu_cpp/hikyuu_server/service/user/SignHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class SignupHandle : public NoAuthRestHandle {
TransAction trans(con);
int count = con->queryInt(fmt::format(R"(select count(id) from {} where name="{}")",
UserModel::getTableName(), user.getName()));
HTTP_CHECK(count == 0, UserErrorCode::USER_NAME_REPETITION, "Duplicate user name");
HTTP_CHECK(count == 0, UserErrorCode::USER_NAME_REPETITION,
_ctr("user", "Duplicate user name"));
user.setUserId(DB::getNewUserId());
con->save(user, false);
}
Expand All @@ -57,9 +58,10 @@ class LoginHandle : public NoAuthRestHandle {
UserModel user;
auto con = DB::getConnect();
con->load(user, fmt::format(R"(name="{}")", req["user"].get<std::string>()));
HTTP_CHECK(user.id() != 0, UserErrorCode::USER_NOT_EXIST, "User does not exist");
HTTP_CHECK(user.id() != 0, UserErrorCode::USER_NOT_EXIST,
_ctr("user", "User does not exist"));
HTTP_CHECK(user.getPassword() == req["password"].get<std::string>(),
UserErrorCode::USER_WRONG_PASSWORD, "Wrong password");
UserErrorCode::USER_WRONG_PASSWORD, _ctr("user", "Wrong password"));

TokenModel token;
{
Expand Down
Loading

0 comments on commit 754353e

Please sign in to comment.