Skip to content

Commit

Permalink
Merge pull request #51 from hezean/i18n-backend
Browse files Browse the repository at this point in the history
feat: i18n backend components
  • Loading branch information
bwcx-jzy committed Jul 4, 2023
2 parents d5e39a5 + fc30948 commit e56cd06
Show file tree
Hide file tree
Showing 19 changed files with 230 additions and 46 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/crowdin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: crowdin

on:
push:
branches: [ dev ]
branches: [ dev, i18n ]
schedule:
- cron: '0 0 * * 0'

Expand All @@ -18,6 +18,7 @@ jobs:
with:
upload_sources: true
upload_translations: true
auto_approve_imported: true
download_translations: true
localization_branch_name: 'i18n/crowdin-sync'
create_pull_request: true
Expand Down
46 changes: 17 additions & 29 deletions crowdin.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
project_id: "TODO"
base_path: "."
base_url: "https://api.crowdin.com"

project_id: 597731
base_path: .
base_url: https://api.crowdin.com
preserve_hierarchy: true

files: [
{
"source": "web-vue/src/locales/zh/*.js",
"translation": "web-vue/src/locales/%two_letters_code%/%original_file_name%",
"ignore": [ "index.js" ],

"type": "js",
files:
- source: 'web-vue/src/locales/zh/*.js'
type: js
translation: 'web-vue/src/locales/%two_letters_code%/%original_file_name%'
escape_quotes: 3
escape_special_characters: 0
ignore:
- index.js

#
# Defines whether single quote should be escaped by another single quote or backslash in exported translations
# e.g. 0 or 1 or 2 or 3 (Default is 3)
# 0 - do not escape single quote;
# 1 - escape single quote by another single quote;
# 2 - escape single quote by backslash;
# 3 - escape single quote by another single quote only in strings containing variables ( {0} ).
#
"escape_quotes": 3,
- source: 'modules/server/src/main/resources/i18n/message_zh.properties'
type: properties
translation: '%original_path%/message_%two_letters_code%.properties'

#
# Defines whether any special characters (=, :, ! and #) should be escaped by backslash in exported translations.
# e.g. 0 or 1 (Default is 0)
# 0 - do not escape special characters
# 1 - escape special characters by a backslash
#
"escape_special_characters": 0
}
]
- source: 'modules/agent/src/main/resources/i18n/message_zh.properties'
type: properties
translation: '%original_path%/message_%two_letters_code%.properties'
4 changes: 4 additions & 0 deletions modules/agent/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,7 @@ spring:
mvc:
throw-exception-if-no-handler-found: true
log-request-details: true
messages:
basename: i18n.message
cache-duration: 3600
encoding: ISO-8859-1
24 changes: 24 additions & 0 deletions modules/agent/src/main/resources/i18n/message.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2019 Code Technology Studio
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

# Base message bundle - do not add translations here
24 changes: 24 additions & 0 deletions modules/agent/src/main/resources/i18n/message_zh.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2019 Code Technology Studio
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

login.success=\u767B\u5F55\u6210\u529F
81 changes: 81 additions & 0 deletions modules/common/src/main/java/org/dromara/jpom/common/I18n.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.dromara.jpom.common;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
import java.util.Objects;

@Slf4j
@Component
@Configuration
public class I18n {

@Resource
private MessageSource messageSource;

public String t(String code, Object... args) {
try {
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
} catch (NoSuchMessageException e) {
// 开发者负责,用户不在意
log.debug("Missing i18n translation, forgot to add one when dev?", e);
return StrUtil.format(code, args);
}
}

@Bean
LocaleResolver localeResolver() {

return new LocaleResolver() {

@Override
public Locale resolveLocale(HttpServletRequest request) {
String header = request.getHeader("Locale");
Locale locale = StringUtils.parseLocale(header);
if (Objects.isNull(locale)) {
locale = Locale.CHINESE;
}
return locale;
}

@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
throw new UnsupportedOperationException("Backend should not change 'Locale' header for requests");
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ public static <T> JsonMessage<T> success(String msg) {
return success(msg, (T) null);
}

public static <T> JsonMessage<T> success(String template, Object... args) {
return success(StrUtil.format(template, args), (T) null);
}

public static <T> JsonMessage<T> success(String msg, T data) {
return new JsonMessage<>(DEFAULT_SUCCESS_CODE, msg, data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,7 @@
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import org.dromara.jpom.common.BaseServerController;
import org.dromara.jpom.common.JsonMessage;
import org.dromara.jpom.common.ServerConst;
import org.dromara.jpom.common.ServerOpenApi;
import org.dromara.jpom.common.*;
import org.dromara.jpom.common.interceptor.LoginInterceptor;
import org.dromara.jpom.common.interceptor.NotLogin;
import org.dromara.jpom.common.validator.ValidatorItem;
Expand Down Expand Up @@ -100,16 +97,19 @@ public class LoginControl extends BaseServerController implements InitializingBe
private final ServerConfig.UserConfig userConfig;
private final ServerConfig.WebConfig webConfig;
private final UserLoginLogServer userLoginLogServer;
private final I18n i18n;

public LoginControl(UserService userService,
UserBindWorkspaceService userBindWorkspaceService,
ServerConfig serverConfig,
UserLoginLogServer userLoginLogServer) {
UserLoginLogServer userLoginLogServer,
I18n i18n) {
this.userService = userService;
this.userBindWorkspaceService = userBindWorkspaceService;
this.userConfig = serverConfig.getUser();
this.webConfig = serverConfig.getWeb();
this.userLoginLogServer = userLoginLogServer;
this.i18n = i18n;
}

/**
Expand Down Expand Up @@ -228,7 +228,7 @@ public JsonMessage<Object> userLogin(@ValidatorItem(value = ValidatorRule.NOT_EM
}
UserLoginDto userLoginDto = this.createToken(userModel);
userLoginLogServer.success(userModel, 0, false, request);
return new JsonMessage<>(200, "登录成功", userLoginDto);
return new JsonMessage<>(200, i18n.t("login.success"), userLoginDto);
} else {
updateModel = userModel.errorLock(userConfig.getAlwaysLoginError());
this.ipError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ public JsonMessage<String> importData(MultipartFile file, HttpServletRequest req
updateCount++;
}
}
return JsonMessage.success("导入成功,添加 {} 条数据,修改 {} 条数据", addCount, updateCount);
// TODO: replace with i18n.t(code, args...)
return JsonMessage.success(String.format("导入成功,添加 %d 条数据,修改 %d 条数据", addCount, updateCount));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ public JsonMessage<String> importData(MultipartFile file, HttpServletRequest req
}
}
projectInfoCacheService.syncExecuteNode(node);
return JsonMessage.success("导入成功,更新 {} 条数据,因为节点分发/项目副本忽略 {} 条数据", updateCount, ignoreCount);
return JsonMessage.success(String.format("导入成功,更新 {} 条数据,因为节点分发/项目副本忽略 {} 条数据", updateCount, ignoreCount));
}

private JSONObject loadProjectData(CsvRow csvRow, String workspaceId, NodeModel node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,6 @@ public JsonMessage<String> importData(MultipartFile file) throws IOException {
updateCount++;
}
}
return JsonMessage.success("导入成功,添加 {} 条数据,修改 {} 条数据", addCount, updateCount);
return JsonMessage.success(String.format("导入成功,添加 {} 条数据,修改 {} 条数据", addCount, updateCount));
}
}
4 changes: 4 additions & 0 deletions modules/server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ spring:
# 上传文件大小限制
max-request-size: 2GB
max-file-size: 1GB
messages:
basename: i18n.message
cache-duration: 3600
encoding: ISO-8859-1
h2:
console:
# 是否开启 web 访问数据库(url: http://${ip}:${port}/h2-console)
Expand Down
24 changes: 24 additions & 0 deletions modules/server/src/main/resources/i18n/message.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2019 Code Technology Studio
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

# Base message bundle - do not add translations here
24 changes: 24 additions & 0 deletions modules/server/src/main/resources/i18n/message_zh.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2019 Code Technology Studio
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

test.agent=\u6D4B\u8BD5 agent {0}
5 changes: 4 additions & 1 deletion web-vue/src/api/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import axios from "axios";
import Qs from "qs";
import store from "../store";
import router from "../router";
import { NO_NOTIFY_KEY, NO_LOADING_KEY, TOKEN_HEADER_KEY, CACHE_WORKSPACE_ID, LOADING_TIP } from "@/utils/const";
import { NO_NOTIFY_KEY, NO_LOADING_KEY, TOKEN_HEADER_KEY, CACHE_WORKSPACE_ID, LOADING_TIP, LOCALE_Header } from "@/utils/const";
import { refreshToken } from "./user/user";

import { notification } from "ant-design-vue";
Expand Down Expand Up @@ -47,6 +47,9 @@ request.interceptors.request.use(
}
config.headers[TOKEN_HEADER_KEY] = store.getters.getToken || "";
config.headers[CACHE_WORKSPACE_ID] = store.getters.getWorkspaceId;
// 后端 i18n
config.headers[LOCALE_Header] = store.getters.getLocale;

return config;
},
(error) => {
Expand Down
2 changes: 2 additions & 0 deletions web-vue/src/utils/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export const LOADING_TIP = "loadingTip";

export const LOCALE_KEY = "locale";

export const LOCALE_Header = "Locale";

const cachePageLimitKeyName = "page_limit";

export function getCachePageLimit() {
Expand Down
Loading

0 comments on commit e56cd06

Please sign in to comment.