From 8ab297e6eb394b9d627a81add790deb4493ae682 Mon Sep 17 00:00:00 2001 From: yanuar Date: Wed, 1 Jul 2020 14:57:17 +0700 Subject: [PATCH] feat: CORE-308 Support multi language and support zh-CN language --- CHANGELOG.md | 5 + Makefile | 3 + package.json | 2 +- scripts/i18nbuilder.js | 2 +- src/lib/service-error-translator/config.json | 2 +- src/lib/service-error-translator/i18n.ts | 32 ++++++- .../service-error-translator.tsx | 32 +++++-- .../translations/zh-CN.json | 95 +++++++++++++++++++ 8 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 src/lib/service-error-translator/translations/zh-CN.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 342bb3f..119e30e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.1.0] +### Added +- Support multi language +- Support zh-CN language + ## [1.0.1] ### Fixed - Ecommerce error translation not showed on Admin Portal diff --git a/Makefile b/Makefile index 4bad9b3..9138892 100644 --- a/Makefile +++ b/Makefile @@ -43,3 +43,6 @@ test: publish: echo 'registry=${NEXUS_REPOSITORY_URL}\nemail=${NEXUS_EMAIL}\nalways-auth=true\n_auth=${NEXUS_AUTH}' > .npmrc npm publish + +pack: + npm pack diff --git a/package.json b/package.json index 69b40d5..e9e9678 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "justice-js-common-utils", - "version": "1.0.1", + "version": "1.1.0", "description": "AccelByte's Justice Common Javascript Utilities", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/scripts/i18nbuilder.js b/scripts/i18nbuilder.js index 84fab17..56fd897 100644 --- a/scripts/i18nbuilder.js +++ b/scripts/i18nbuilder.js @@ -139,6 +139,6 @@ function run({ files, languages, directory }) { const tsxFiles = findFilesInDirectory(path.resolve(__dirname, "../src/lib/service-error-translator"), ".tsx"); run({ files: tsxFiles, - languages: ["en-US"], + languages: ["en-US", "zh-CN"], directory: path.resolve(__dirname, "../src/lib/service-error-translator/translations"), }); diff --git a/src/lib/service-error-translator/config.json b/src/lib/service-error-translator/config.json index 9a5df70..ac90f02 100644 --- a/src/lib/service-error-translator/config.json +++ b/src/lib/service-error-translator/config.json @@ -1,5 +1,5 @@ { - "languageCodes": ["en-US"], + "languageCodes": ["en-US", "zh-CN"], "defaultLanguage": "en-US", "fallbackLanguage": "en-US" } diff --git a/src/lib/service-error-translator/i18n.ts b/src/lib/service-error-translator/i18n.ts index f19b34b..b1695ba 100644 --- a/src/lib/service-error-translator/i18n.ts +++ b/src/lib/service-error-translator/i18n.ts @@ -8,10 +8,26 @@ import flatten from "flat"; import i18next, { Resource } from "i18next"; import { initReactI18next } from "react-i18next"; import config from "./config.json"; +import enUS from "./translations/en-US.json"; +import zhCN from "./translations/zh-CN.json"; -const loadedLanguages: { [key: string]: string } = { - "en-US": "enUS", +function isOnBrowser() { + try { + if (window) { + return true; + } + // eslint-disable-next-line + } catch (error) { + console.error(error); + } + return false; +} + +const loadedLanguages: { [key: string]: { [key: string]: string } } = { + "en-US": enUS, + "zh-CN": zhCN, }; +const languageLocalStorageKey = "i18nextLng"; const availableLanguageCodes = config.languageCodes; const translationResource = availableLanguageCodes.reduce((resources: Resource, languageCode: string) => { // eslint-disable-next-line no-param-reassign @@ -22,10 +38,20 @@ const translationResource = availableLanguageCodes.reduce((resources: Resource, return resources; }, {}); +export function getLocalStorageLanguage(): string { + if (isOnBrowser()) { + const currentLanguageCode = localStorage.getItem(languageLocalStorageKey); + if (currentLanguageCode && availableLanguageCodes.includes(currentLanguageCode)) { + return currentLanguageCode; + } + } + return config.defaultLanguage; +} + // @ts-ignore export const i18nInstance = i18next.use(initReactI18next).createInstance( { - lng: config.defaultLanguage, + lng: getLocalStorageLanguage(), fallbackLng: config.fallbackLanguage, preload: availableLanguageCodes, resources: translationResource, diff --git a/src/lib/service-error-translator/service-error-translator.tsx b/src/lib/service-error-translator/service-error-translator.tsx index 344c0b2..9d0f172 100644 --- a/src/lib/service-error-translator/service-error-translator.tsx +++ b/src/lib/service-error-translator/service-error-translator.tsx @@ -5,15 +5,14 @@ */ import * as React from "react"; -import { Trans } from "react-i18next"; +import { I18nextProvider, Trans } from "react-i18next"; import { BasicAdminErrorTranslationMap } from "./error-translation-map/basic-admin-error-translation-map"; import { BasicErrorTranslationMap } from "./error-translation-map/basic-error-translation-map"; import { EcommerceErrorTranslationMap } from "./error-translation-map/ecommerce-error-translation-map"; import { IAMAdminErrorTranslationMap } from "./error-translation-map/iam-admin-error-translation-map"; import { IAMErrorTranslationMap } from "./error-translation-map/iam-error-translation-map"; -import { - StatisticAdminErrorTranslationMap, -} from "./error-translation-map/statistic-admin-error-translation-map"; +import { StatisticAdminErrorTranslationMap } from "./error-translation-map/statistic-admin-error-translation-map"; +import { getLocalStorageLanguage, i18nInstance } from "./i18n"; interface ServiceErrorProps { errorCode: number; @@ -31,18 +30,31 @@ export const ServiceErrorTranslator = (props: ServiceErrorProps) => { return null; }; -export const translateServiceError = (errorCode: number) => { +export const Withi18nProvider = ({ children, lang }: { children: React.ReactNode, lang?: string }) => { + i18nInstance.changeLanguage(lang || getLocalStorageLanguage()); + return {children}; +}; + +export const translateServiceError = (errorCode: number, lang?: string) => { if (isValidServiceError(errorCode) && errorCode in serviceErrorTranslationMap) { - return serviceErrorTranslationMap[errorCode]; + return {serviceErrorTranslationMap[errorCode]}; } - return Failed to complete the request; + return ( + + Failed to complete the request + + ); }; -export const translateServiceErrorForAdmin = (errorCode: number) => { +export const translateServiceErrorForAdmin = (errorCode: number, lang?: string) => { if (isValidServiceError(errorCode) && errorCode in adminServiceErrorTranslationMap) { - return adminServiceErrorTranslationMap[errorCode]; + return adminServiceErrorTranslationMap[errorCode]; } - return Failed to complete the request; + return ( + + Failed to complete the request + + ); }; const serviceErrorTranslationMap: { [key: string]: React.ReactNode } = Object.freeze({ diff --git a/src/lib/service-error-translator/translations/zh-CN.json b/src/lib/service-error-translator/translations/zh-CN.json new file mode 100644 index 0000000..11fca54 --- /dev/null +++ b/src/lib/service-error-translator/translations/zh-CN.json @@ -0,0 +1,95 @@ +{ + "adminServiceError.10130": "年龄不符合年龄限制", + "adminServiceError.10133": "电子邮件地址已被使用", + "adminServiceError.10136": "验证码已被使用", + "adminServiceError.10137": "验证码已过期", + "adminServiceError.10138": "验证码不匹配", + "adminServiceError.10139": "平台帐户不存在", + "adminServiceError.10140": "用户已经过验证", + "adminServiceError.10145": "只有出版商管理员可以执行此操作", + "adminServiceError.10146": "用户ID不匹配", + "adminServiceError.10148": "不正确的上下文", + "adminServiceError.10149": "接触式的不匹配", + "adminServiceError.10152": "出了些问题。请与管理员联系。", + "adminServiceError.10153": "用户已存在", + "adminServiceError.10154": "国家不存在", + "adminServiceError.10156": "角色不存在", + "adminServiceError.10157": "角色不存在", + "adminServiceError.10158": "禁令并不存在", + "adminServiceError.10159": "只有角色管理器可以执行此操作", + "adminServiceError.10160": "用户已经有作用", + "adminServiceError.10161": "用户已注册为角色成员", + "adminServiceError.10169": "年龄限制不存在", + "adminServiceError.10170": "用户已经拥有平台账号", + "adminServiceError.10171": "电子邮件地址未注册", + "adminServiceError.10364": "客户端已经存在", + "adminServiceError.10365": "客户端不存在", + "adminServiceError.10456": "角色不存在", + "adminServiceError.10457": "无法添加角色成员,该角色是不是管理员角色", + "adminServiceError.10459": "只有角色管理器可以执行此操作", + "adminServiceError.10466": "无效的角色成员", + "adminServiceError.10467": "管理员角色必须拥有至少1角色管理器", + "adminServiceError.10468": "用户已注册为角色管理器", + "adminServiceError.10469": "用户已注册为角色成员", + "adminServiceError.11132": "你已经达到了最大上传限制", + "adminServiceError.11233": "区域不存在", + "adminServiceError.11234": "全国已经注册在另一区域", + "adminServiceError.11235": "地区已经存在", + "adminServiceError.11336": "命名空间已经存在", + "adminServiceError.11337": "命名空间不存在", + "adminServiceError.11440": "用户配置文件不存在", + "adminServiceError.11540": "用户配置文件不存在", + "adminServiceError.20000": "出了些问题。请与管理员联系。", + "adminServiceError.20001": "很抱歉,您不授权选定操作", + "adminServiceError.20002": "请更正表格中的错误进行", + "adminServiceError.20006": "该项目已被另一管理员更新。请刷新页面。", + "adminServiceError.20007": "您已经请求了太多的代码。请稍后再试。", + "adminServiceError.20008": "用户不存在", + "adminServiceError.20013": "对不起,您无权做这个动作或访问此页", + "adminServiceError.20019": "出了些问题。请与管理员联系。", + "adminServiceError.20022": "出了些问题。你发送一个无效的请求。", + "adminServiceError.70131": "配置中不存在", + "adminServiceError.70132": "配置已经存在", + "adminServiceError.70330": "对不起,我们无法处理此请求", + "adminServiceError.70331": "配置中不存在", + "adminServiceError.70334": "统计值不decreasable。", + "adminServiceError.70335": "用户统计项目不存在", + "adminServiceError.70336": "用户统计项目已经存在", + "adminServiceError.70337": "您已到达统计的最大值", + "serviceError.10130": "对不起,我们无法处理此请求", + "serviceError.10133": "很抱歉,您必须输入新的电子邮件地址", + "serviceError.10136": "对不起,您输入的代码已被使用。请resquest一个新的。", + "serviceError.10137": "对不起,您输入的代码已过期。请申请一个新的。", + "serviceError.10138": "对不起,您输入的代码是无效的。请再试一遍。", + "serviceError.10139": "哎呀,好像你还没有玩游戏呢。请玩游戏,用这个动作之前进行", + "serviceError.10140": "用户已经过验证", + "serviceError.10142": "对不起,您的新密码不能是相同的旧", + "serviceError.10143": "您所输入的密码不匹配。请确保你输入了正确的密码", + "serviceError.10148": "出了些问题。欲了解更多信息,请联系我们的hello@accelbyte.io支持", + "serviceError.10149": "出了些问题。欲了解更多信息,请联系我们的hello@accelbyte.io支持", + "serviceError.10152": "出了些问题。欲了解更多信息,请联系我们的hello@accelbyte.io支持", + "serviceError.10153": "用户已存在", + "serviceError.10154": "国家不存在", + "serviceError.10170": "哎呀,你已经挂您的电子邮件地址到您的帐户。", + "serviceError.10171": "此电子邮件地址未注册", + "serviceError.10172": "对不起,您的帐户已链接。", + "serviceError.10173": "对不起,平台帐户已与其他用户账户链接。", + "serviceError.10174": "哎呀,你要连接的平台不存在。请尝试其他平台。", + "serviceError.11132": "你已经达到了最大上传限制。", + "serviceError.11233": "错误:国家组不存在。如果您看到此错误,请hello@accelbyte.io立即帮助联系我们的支持", + "serviceError.11337": "错误:用户的个人资料不存在。如果您看到此错误,请hello@accelbyte.io立即帮助联系我们的支持", + "serviceError.11440": "错误:用户的个人资料不存在。如果您看到此错误,请hello@accelbyte.io立即帮助联系我们的支持", + "serviceError.11441": "错误:用户配置文件已经存在。如果您看到此错误,请hello@accelbyte.io立即帮助联系我们的支持", + "serviceError.20000": "出了些问题。欲了解更多信息,请联系我们的hello@accelbyte.io支持", + "serviceError.20001": "很抱歉,您要访问的页面不向公众提供。", + "serviceError.20002": "请更正表格中的错误进行", + "serviceError.20007": "您已经请求了太多的代码。请稍后再试。", + "serviceError.20008": "错误:用户不存在。如果您看到此错误,请hello@accelbyte.io立即帮助联系我们的支持", + "serviceError.20013": "对不起,您无权做这个动作或访问此页", + "serviceError.20017": "哎呀,好像你还没有玩游戏呢。请玩游戏,用这个动作之前进行", + "serviceError.20019": "出了些问题。欲了解更多信息,请联系我们的hello@accelbyte.io支持", + "serviceError.20022": "出了些问题。欲了解更多信息,请联系我们的hello@accelbyte.io支持", + "serviceError.38171": "很抱歉,您已拥有这项商品", + "serviceError.30122": "商店草案应具有相同的默认语言,默认域和命名空间与公布的商店。", + "serviceError.unknown": "无法完成请求" +}