This commit is contained in:
devezhao 2021-05-15 18:10:19 +08:00
parent 8823414446
commit dd7a22d5d7
37 changed files with 215 additions and 205 deletions

View file

@ -22,7 +22,6 @@ import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
import com.rebuild.core.privileges.UserHelper;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.service.project.ProjectManager;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.utils.AppUtils;
import com.rebuild.utils.JSONUtils;
import lombok.extern.slf4j.Slf4j;
@ -34,6 +33,8 @@ import org.jsoup.nodes.Element;
import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 导航渲染
*
@ -55,15 +56,15 @@ public class NavBuilder extends NavManager {
private static final JSONArray NAVS_DEFAULT = JSONUtils.toJSONObjectArray(
NAV_ITEM_PROPS,
new Object[][] {
new Object[] { "chart-donut", "{Feeds}", "BUILTIN", NAV_FEEDS },
new Object[] { "shape", "{Project}", "BUILTIN", NAV_PROJECT },
new Object[] { "folder", "{File}", "BUILTIN", NAV_FILEMRG }
new Object[] { "chart-donut", $L("动态"), "BUILTIN", NAV_FEEDS },
new Object[] { "shape", $L("项目"), "BUILTIN", NAV_PROJECT },
new Object[] { "folder", $L("文件"), "BUILTIN", NAV_FILEMRG }
});
// 新建项目
private static final JSONObject NAV_PROJECT__ADD = JSONUtils.toJSONObject(
NAV_ITEM_PROPS,
new String[] { "plus", "{AddProject}", "BUILTIN", NAV_PROJECT + "--add" }
new String[] { "plus", $L("添加项目"), "BUILTIN", NAV_PROJECT + "--add" }
);
// URL 绑定实体权限
@ -178,7 +179,7 @@ public class NavBuilder extends NavManager {
* @param initEntity
*/
public void addInitNavOnInstall(String[] initEntity) {
JSONArray initNav = (JSONArray) Language.getCurrentBundle().replaceLangKey(NAVS_DEFAULT);
JSONArray initNav = replaceLangKey(NAVS_DEFAULT);
for (String e : initEntity) {
EasyEntity entity = EasyMetaFactory.valueOf(e);
@ -215,7 +216,7 @@ public class NavBuilder extends NavManager {
if (activeNav == null) activeNav = "dashboard-home";
JSONArray navs = NavBuilder.instance.getUserNav(AppUtils.getRequestUser(request));
navs = (JSONArray) AppUtils.getReuqestBundle(request).replaceLangKey(navs);
navs = replaceLangKey(navs);
StringBuilder navsHtml = new StringBuilder();
for (Object item : navs) {
@ -321,4 +322,9 @@ public class NavBuilder extends NavManager {
}
return navHtml.toString();
}
private static JSONArray replaceLangKey(JSONArray resource) {
// TODO 导航条语言替换 ???
return (JSONArray) resource.clone();
}
}

View file

@ -25,7 +25,7 @@ import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.List;
import static com.rebuild.core.support.i18n.I18nUtils.$L;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 实体元数据

View file

@ -26,6 +26,7 @@ import com.rebuild.core.service.notification.Message;
import com.rebuild.core.service.notification.MessageBuilder;
import com.rebuild.core.support.ConfigurationItem;
import com.rebuild.core.support.RebuildConfiguration;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.i18n.LanguageBundle;
import com.rebuild.core.support.integration.SMSender;
import com.rebuild.core.support.task.TaskExecutors;
@ -237,9 +238,8 @@ public class UserService extends BaseServiceImpl {
String appName = RebuildConfiguration.get(ConfigurationItem.AppName);
String homeUrl = RebuildConfiguration.getHomeUrl();
LanguageBundle bundle = Application.getLanguage().getDefaultBundle();
String content = bundle.$L(
"系统管理员已经为你开通了 %s 账号!以下为你的登录信息,请妥善保管。 [] 登录账号 : **%s** [] 登录密码 : **%s** [] 登录地址 : [%s](%s) [][] 首次登陆,建议你立即修改登陆密码。修改方式 : 登陆后点击右上角头像 - 个人设置 - 安全设置 - 更改密码",
LanguageBundle bundle = Language.getSysDefaultBundle();
String content = bundle.$L("系统管理员已经为你开通了 %s 账号!以下为你的登录信息,请妥善保管。 [] 登录账号 : **%s** [] 登录密码 : **%s** [] 登录地址 : [%s](%s) [][] 首次登陆,建议你立即修改登陆密码。修改方式 : 登陆后点击右上角头像 - 个人设置 - 安全设置 - 更改密码",
appName, newUser.getString("loginName"), passwd, homeUrl, homeUrl);
SMSender.sendMailAsync(newUser.getString("email"), $L("你的账号已就绪"), content);
@ -363,8 +363,8 @@ public class UserService extends BaseServiceImpl {
// 通知管理员
ID newUserId = record.getPrimary();
String viewUrl = AppUtils.getContextPath() + "/app/list-and-view?id=" + newUserId;
String content = $L("用户 @%s 提交了注册申请。请验证用户有效性后为其指定部门和角色,激活用户登录。" +
"如果这是一个无效的申请请忽略。[点击开始激活](%s)", newUserId, viewUrl);
String content = $L("用户 @%s 提交了注册申请。请验证用户有效性后为其指定部门和角色,激活用户登录。如果这是一个无效的申请请忽略。[点击开始激活](%s)",
newUserId, viewUrl);
Message message = MessageBuilder.createMessage(ADMIN_USER, content, newUserId);
Application.getNotifications().send(message);

View file

@ -16,7 +16,8 @@ import com.rebuild.core.service.notification.Message;
import com.rebuild.core.service.notification.MessageBuilder;
import com.rebuild.core.support.RebuildConfiguration;
import com.rebuild.core.support.distributed.DistributedJobLock;
import com.rebuild.core.support.i18n.I18nUtils;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.i18n.LanguageBundle;
import com.rebuild.core.support.integration.SMSender;
import com.rebuild.utils.AppUtils;
import org.springframework.scheduling.annotation.Scheduled;
@ -66,6 +67,7 @@ public class FeedsScheduleJob extends DistributedJobLock {
list.add(o);
}
final LanguageBundle bundle = Language.getSysDefaultBundle();
// 发送
for (List<Object[]> list : map.values()) {
List<Object[]> notifications = new ArrayList<>();
@ -80,12 +82,11 @@ public class FeedsScheduleJob extends DistributedJobLock {
if ((reminds & 4) != 0) smss.add(o);
}
final ID toUser = (ID) list.get(0)[0];
final String subjectTemp = I18nUtils.getSysDefaultBundle().$L("你有 %d 条日程提醒");
ID toUser = (ID) list.get(0)[0];
// 消息通知
if (!notifications.isEmpty()) {
String subject = String.format(subjectTemp, notifications.size());
String subject = bundle.$L("你有 %d 条日程提醒", notifications.size());
String contents = subject + mergeContents(notifications, false);
Application.getNotifications().send(
MessageBuilder.createMessage(toUser, contents, Message.TYPE_FEEDS));
@ -94,7 +95,7 @@ public class FeedsScheduleJob extends DistributedJobLock {
// 邮件
final String emailAddr = Application.getUserStore().getUser(toUser).getEmail();
if (SMSender.availableMail() && RegexUtils.isEMail(emailAddr) && !emails.isEmpty()) {
String subject = String.format(subjectTemp, emails.size());
String subject = bundle.$L("你有 %d 条日程提醒", emails.size());
String contents = mergeContents(emails, true);
contents = MessageBuilder.formatMessage(contents, true, false);
SMSender.sendMailAsync(emailAddr, subject, contents);
@ -103,7 +104,7 @@ public class FeedsScheduleJob extends DistributedJobLock {
// 短信考虑短信字数内容简化了
final String mobileAddr = Application.getUserStore().getUser(toUser).getWorkphone();
if (SMSender.availableSMS() && RegexUtils.isCNMobile(mobileAddr) && !smss.isEmpty()) {
String subject = String.format(subjectTemp, smss.size());
String subject = bundle.$L("你有 %d 条日程提醒", smss.size());
SMSender.sendSMSAsync(mobileAddr, subject);
}
}

View file

@ -59,6 +59,7 @@ import static com.rebuild.core.support.i18n.Language.$L;
@Service
public class GeneralEntityService extends ObservableService implements EntityService {
@SuppressWarnings("deprecation")
protected GeneralEntityService(PersistManagerFactory aPMFactory) {
super(aPMFactory);

View file

@ -8,7 +8,6 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.core.support.i18n;
import cn.devezhao.commons.CalendarUtils;
import com.rebuild.core.Application;
import java.util.Date;
@ -38,12 +37,4 @@ public class I18nUtils {
public static String $L(String key, Object... placeholders) {
return Language.$L(key, placeholders);
}
/**
* @return
* @see Language#getDefaultBundle()
*/
public static LanguageBundle getSysDefaultBundle() {
return Application.getLanguage().getDefaultBundle();
}
}

View file

@ -43,11 +43,11 @@ public class Language implements Initialization {
@Override
public void init() throws IOException {
bundleMap.put("zh_CN", LanguageBundle.DEFAULT_BUNDLE);
bundleMap.put(LanguageBundle.SYS_LC, LanguageBundle.SYS_BUNDLE);
File[] langFiles = new ClassPathResource("i18n/").getFile().listFiles(pathname -> {
String name = pathname.getName();
return name.startsWith("language.") && name.endsWith(".json");
return name.startsWith("lang.") && name.endsWith(".json");
});
if (langFiles == null) return;
@ -90,7 +90,7 @@ public class Language implements Initialization {
* @see java.util.Locale
*/
public LanguageBundle getBundle(String locale) {
if (Application.isWaitLoad()) return LanguageBundle.DEFAULT_BUNDLE;
if (Application.isWaitLoad()) return LanguageBundle.SYS_BUNDLE;
if (locale != null) {
if (bundleMap.containsKey(locale)) {
@ -114,7 +114,7 @@ public class Language implements Initialization {
public LanguageBundle getDefaultBundle() {
String d = RebuildConfiguration.get(ConfigurationItem.DefaultLanguage);
if (available(d) == null) {
return LanguageBundle.DEFAULT_BUNDLE;
return LanguageBundle.SYS_BUNDLE;
} else {
return bundleMap.get(d);
}
@ -171,8 +171,16 @@ public class Language implements Initialization {
// -- Quick Methods
/**
* 当前用户语言包线程量用户
*
* 获取默认语言
* @return
* @see Language#getDefaultBundle()
*/
public static LanguageBundle getSysDefaultBundle() {
return Application.getLanguage().getDefaultBundle();
}
/**
* 获取当前用户语言
* @return
* @see UserContextHolder#getLocale()
*/

View file

@ -8,12 +8,9 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.core.support.i18n;
import cn.devezhao.commons.EncryptUtils;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.core.Application;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.support.License;
import com.rebuild.utils.AppUtils;
import com.rebuild.utils.JSONUtils;
@ -47,11 +44,6 @@ public class LanguageBundle implements JSONable {
// 代码
private static final Pattern CODE_PATT = Pattern.compile("`(.*?)`");
protected static final String PREFIX_ENTITY = "e.";
protected static final String PREFIX_FIELD = "f.";
protected static final String PREFIX_DISPLAY_TYPE = "t.";
protected static final String PREFIX_STATE = "s.";
private String locale;
private JSONObject bundle;
private String bundleHash;
@ -72,19 +64,30 @@ public class LanguageBundle implements JSONable {
* @return
*/
private JSONObject merge(JSONObject bundle) {
if (Application.isReady()) {
appendMetadata(bundle);
if (License.isCommercial()) {
appendDatabase(bundle);
}
if (Application.isReady() && License.isCommercial()) {
appendDatabase(bundle);
}
String bundleString = bundle.toJSONString();
JSONObject newBundle = new JSONObject();
for (String key : bundle.keySet()) {
String value = bundle.getString(key);
newBundle.put(key, formatLang(value));
}
bundleString = BR_PATT.matcher(bundleString).replaceAll("<br/>");
this.bundleHash = EncryptUtils.toMD5Hex(newBundle.toJSONString());
return newBundle;
}
Matcher matcher = LINK_PATT.matcher(bundleString);
/**
* MD 语法支持
*
* @param content
* @return
*/
private String formatLang(String content) {
content = BR_PATT.matcher(content).replaceAll("<br/>");
Matcher matcher = LINK_PATT.matcher(content);
while (matcher.find()) {
String text = matcher.group(1);
String url = matcher.group(2);
@ -96,45 +99,29 @@ public class LanguageBundle implements JSONable {
link = "<a href='" + AppUtils.getContextPath() + "%s'>%s</a>";
}
bundleString = bundleString.replace(
String.format("[%s](%s)", text, url),
String.format(link, url, text));
content = content.replace(
String.format("[%s](%s)", text, url), String.format(link, url, text));
}
matcher = BOLD_PATT.matcher(bundleString);
matcher = BOLD_PATT.matcher(content);
while (matcher.find()) {
String text = matcher.group(1);
String bold = "<b>%s</b>";
bundleString = bundleString.replace(String.format("**%s**", text), String.format(bold, text));
content = content.replace(
String.format("**%s**", text), String.format(bold, text));
}
matcher = CODE_PATT.matcher(bundleString);
matcher = CODE_PATT.matcher(content);
while (matcher.find()) {
String text = matcher.group(1);
String code = "<code>%s</code>";
bundleString = bundleString.replace(String.format("`%s`", text), String.format(code, text));
content = content.replace(
String.format("`%s`", text), String.format(code, text));
}
this.bundleHash = EncryptUtils.toMD5Hex(bundleString);
return JSON.parseObject(bundleString);
}
/**
* 元数据
* @param bundle
*/
protected void appendMetadata(JSONObject bundle) {
for (Entity entity : MetadataHelper.getEntities()) {
bundle.put(PREFIX_ENTITY + entity.getName(),
entity.getDescription().split(" \\(")[0]);
for (Field field : entity.getFields()) {
if (!MetadataHelper.isCommonsField(field)) {
bundle.put(PREFIX_FIELD + entity.getName() + "." + field.getName(),
field.getDescription().split(" \\(")[0]);
}
}
}
return content;
}
/**
@ -192,7 +179,8 @@ public class LanguageBundle implements JSONable {
// --
static final LanguageBundle DEFAULT_BUNDLE = new LanguageBundle();
static final String SYS_LC = "zh_CN";
static final LanguageBundle SYS_BUNDLE = new LanguageBundle();
private LanguageBundle() {
this.bundle = JSONUtils.EMPTY_OBJECT;

View file

@ -11,7 +11,6 @@ import cn.devezhao.commons.web.ServletUtils;
import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSON;
import com.rebuild.api.Controller;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.utils.AppUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
@ -44,30 +43,6 @@ public abstract class BaseController extends Controller {
return user;
}
/**
* @param request
* @param key
* @param phKey
* @return
* @see AppUtils#getReuqestBundle(HttpServletRequest)
* @see Language#L(String, String...)
*/
protected String getLang(HttpServletRequest request, String key, String... phKey) {
return AppUtils.getReuqestBundle(request).getLang(key, phKey);
}
/**
* @param request
* @param key
* @param phValues
* @return
* @see AppUtils#getReuqestBundle(HttpServletRequest)
* @see Language#LF(String, Object...)
*/
protected String formatLang(HttpServletRequest request, String key, Object... phValues) {
return AppUtils.getReuqestBundle(request).formatLang(key, phValues);
}
/**
* @param response
*/

View file

@ -28,6 +28,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author devezhao
* @since 10/13/2018
@ -47,7 +49,7 @@ public class AdminVerfiyController extends BaseController {
if (admin.isAdmin()) {
return createModelAndView("/admin/admin-verify");
} else {
response.sendError(403, getLang(request, "NoneAdmin"));
response.sendError(403, $L("非管理员用户"));
return null;
}
}

View file

@ -192,12 +192,12 @@ public class ConfigurationController extends BaseController {
specAccount[1] = RebuildConfiguration.get(ConfigurationItem.SmsPassword);
}
String content = getLang(request, "SendTestMessage", "Sms");
String content = $L("收到此消息说明你的短信服务配置正确");
sent = SMSender.sendSMS(receiver, content, specAccount);
} else if ("EMAIL".equalsIgnoreCase(type)) {
if (!RegexUtils.isEMail(receiver)) {
return RespBody.errorl("SomeInvalid", "Email");
return RespBody.errorl("无效邮箱地址");
}
String[] specAccount = new String[]{
@ -209,7 +209,7 @@ public class ConfigurationController extends BaseController {
specAccount[1] = RebuildConfiguration.get(ConfigurationItem.MailPassword);
}
String content = getLang(request, "SendTestMessage", "Email");
String content = $L("收到此消息说明你的邮件服务配置正确");
sent = SMSender.sendMail(receiver, content, content, true, specAccount);
}

View file

@ -40,6 +40,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author devezhao
* @since 10/08/2018
@ -128,6 +130,7 @@ public class UserController extends EntityController {
if (roleNew != null) {
set.remove(deptNew);
} else if (enUser.getOwningRole() != null) {
// noinspection SuspiciousMethodCalls
set.remove(enUser.getOwningRole().getIdentity());
}
@ -154,8 +157,9 @@ public class UserController extends EntityController {
if (did == null) {
String homeUrl = RebuildConfiguration.getHomeUrl();
String subject = getLang(request, "YourAccountActive");
String content = String.format(getLang(request, "NewUserAccountActive"), enUser.getFullName(), homeUrl, homeUrl);
String subject = $L("你的账户已激活");
String content = $L("%s 你的账户已激活!现在你可以登陆并使用系统。 [][] 登录地址 : [%s](%s) [][] 首次登陆,建议你立即修改密码!如有任何登陆或使用问题,请与系统管理员联系。",
enUser.getFullName(), homeUrl, homeUrl);
SMSender.sendMailAsync(enUser.getEmail(), subject, content);
}

View file

@ -43,6 +43,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author devezhao
* @since 01/03/2019
@ -63,7 +65,7 @@ public class DataImportController extends BaseController {
String file = getParameterNotNull(request, "file");
File tmp = getFileOfImport(file);
if (tmp == null) {
writeFailure(response, getLang(request, "SomeInvalid,DataFile"));
writeFailure(response, $L("数据文件无效"));
return;
}
@ -75,7 +77,7 @@ public class DataImportController extends BaseController {
preview = parser.parse(11);
} catch (Exception ex) {
log.error("Parse excel error : " + file, ex);
writeFailure(response, getLang(request, "NotParseDataFile"));
writeFailure(response, $L("无法解析数据,请检查数据文件格式"));
return;
}
@ -134,13 +136,13 @@ public class DataImportController extends BaseController {
String defaultValue = null;
if (EntityHelper.CreatedOn.equals(fieldName)
|| EntityHelper.ModifiedOn.equals(fieldName)) {
defaultValue = getLang(request, "CurrentTime");
defaultValue = $L("当前时间");
} else if (EntityHelper.CreatedBy.equals(fieldName)
|| EntityHelper.ModifiedBy.equals(fieldName)
|| EntityHelper.OwningUser.equals(fieldName)) {
defaultValue = getLang(request, "CurrentUser");
defaultValue = $L("当前用户");
} else if (easyMeta.getDisplayType() == DisplayType.SERIES) {
defaultValue = getLang(request, "t.SERIES");
defaultValue = $L("自动编号");
}
if (defaultValue != null) {

View file

@ -37,6 +37,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* Excel 报表
*
@ -75,7 +77,7 @@ public class ReportTemplateController extends BaseController {
Map<String, String> vars = new TemplateExtractor(template, true).transformVars(entityMeta);
if (vars.isEmpty()) {
writeFailure(response, getLang(request, "BadReportTemplate"));
writeFailure(response, $L("无效模板文件 (未找到有效字段)"));
return;
}
@ -87,7 +89,7 @@ public class ReportTemplateController extends BaseController {
}
if (invalidVars.size() >= vars.size()) {
writeFailure(response, getLang(request, "BadReportTemplate"));
writeFailure(response, $L("无效模板文件 (未找到有效字段)"));
return;
}
@ -108,7 +110,7 @@ public class ReportTemplateController extends BaseController {
entity.getPrimaryField().getName(), entity.getName());
Object[] random = Application.createQueryNoFilter(sql).unique();
if (random == null) {
response.sendError(400, getLang(request, "NoRecordForPreview"));
response.sendError(400, $L("未找到可供预览的记录"));
return;
}
@ -117,7 +119,7 @@ public class ReportTemplateController extends BaseController {
File template = DataReportManager.instance.getTemplateFile(entity, reportId);
file = new EasyExcelGenerator(template, (ID) random[0]).generate();
} catch (ConfigurationException ex) {
response.sendError(400, getLang(request, "NoFileForPreview"));
response.sendError(400, $L("未找到可供预览的记录"));
return;
}

View file

@ -29,6 +29,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 分类数据管理
*
@ -52,7 +54,7 @@ public class ClassificationController extends BaseController {
.setParameter(1, id)
.unique();
if (data == null) {
resp.sendError(404, getLang(request, "SomeNotExists", "Classification"));
resp.sendError(404, $L("分类数据不存在"));
return null;
}

View file

@ -45,6 +45,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author zhaofang123@gmail.com
* @since 08/03/2018
@ -134,18 +136,16 @@ public class MetaEntityController extends BaseController {
String mainEntity = reqJson.getString("mainEntity");
if (StringUtils.isNotBlank(mainEntity)) {
if (!MetadataHelper.containsEntity(mainEntity)) {
writeFailure(response,
getLang(request, "SomeInvalid", "MainEntity") + " : " + mainEntity);
writeFailure(response, $L("无效主实体 (%s)", mainEntity));
return;
}
Entity useMain = MetadataHelper.getEntity(mainEntity);
if (useMain.getMainEntity() != null) {
writeFailure(response, getLang(request, "DetailEntityNotBeMain"));
writeFailure(response, $L("明细实体不能作为主实体"));
return;
} else if (useMain.getDetailEntity() != null) {
writeFailure(response,
String.format(getLang(request, "SelectMainEntityBeXUsed"), useMain.getDetailEntity()));
writeFailure(response, $L("选择的主实体已被 [%s] 使用", useMain.getDetailEntity()));
return;
}
}

View file

@ -40,6 +40,8 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author devezhao
* @since 2019/11/25
@ -73,7 +75,7 @@ public class InstallController extends BaseController implements InstallState {
Installer checker = new Installer(props);
try (Connection conn = checker.getConnection(null)) {
DatabaseMetaData dmd = conn.getMetaData();
String okMsg = formatLang(request, "ConnectionSucceed",
String okMsg = $L("连接成功 : %s",
dmd.getDatabaseProductName() + " " + dmd.getDatabaseProductVersion());
// 查询表
@ -83,8 +85,7 @@ public class InstallController extends BaseController implements InstallState {
if (hasTable != null) {
// 挂载模式
if (checker.isRbDatabase()) {
okMsg += String.format(" (%s)",
formatLang(request, "NoneEmptyDbTips", dbProps.getString("dbName")));
okMsg += $L("已发现 **%s** 为 REBUILD 数据库,系统将自动挂载", dbProps.getString("dbName"));
okMsg = "1#" + okMsg;
} else {
return RespBody.errorl("NoneEmptyDbError");
@ -98,11 +99,10 @@ public class InstallController extends BaseController implements InstallState {
} catch (SQLException ex) {
if (ex.getLocalizedMessage().contains("Unknown database")) {
String okMsg = formatLang(request, "ConnectionSucceedEmptyDbTips",
dbProps.getString("dbName"));
String okMsg = $L("连接成功 : 数据库 **%s** 不存在,系统将自动创建", dbProps.getString("dbName"));
return RespBody.ok(okMsg);
} else {
return RespBody.error(formatLang(request, "ConnectionError", ex.getLocalizedMessage()));
return RespBody.errorl("连接错误 : %s", ex.getLocalizedMessage());
}
}
}
@ -124,11 +124,10 @@ public class InstallController extends BaseController implements InstallState {
}
pool.destroy();
return RespBody.ok(formatLang(request, "ConnectionSucceed", info));
return RespBody.ok($L("连接成功 : %s", info));
} catch (Exception ex) {
return RespBody.error(
formatLang(request, "ConnectionError", ThrowableUtils.getRootCause(ex).getLocalizedMessage()));
return RespBody.errorl("连接错误 : %s", ThrowableUtils.getRootCause(ex).getLocalizedMessage());
}
}
@ -151,8 +150,7 @@ public class InstallController extends BaseController implements InstallState {
return RespBody.ok();
} catch (Exception ex) {
log.error("An error occurred during install", ex);
return RespBody.error(
getLang(request, "InstallFailed") + " : " + ThrowableUtils.getRootCause(ex).getLocalizedMessage());
return RespBody.errorl("安装失败 : %s", ThrowableUtils.getRootCause(ex).getLocalizedMessage());
}
}
}

View file

@ -20,6 +20,8 @@ import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author zhaofang123@gmail.com
* @see com.rebuild.web.RebuildWebConfigurer
@ -29,10 +31,11 @@ import javax.servlet.http.HttpServletResponse;
public class ErrorPageView extends BaseController {
@GetMapping("/error/unsupported-browser")
public ModelAndView pageUnsupportedBrowser(HttpServletRequest request) {
public ModelAndView pageUnsupportedBrowser() {
ModelAndView mv = createModelAndView("/error/error");
mv.getModelMap().put("error_code", 400);
mv.getModelMap().put("error_msg", getLang(request, "UnsupportIE10"));
mv.getModelMap().put("error_msg",
$L("不支持 IE10 及以下的浏览器 [] 推荐使用 Edge、Chrome、Firefox 或 IE11"));
return mv;
}

View file

@ -37,6 +37,8 @@ import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 文件下载/查看
*
@ -139,7 +141,7 @@ public class FileDownloader extends BaseController {
if (request.getRequestURI().contains("/filex/access/")) {
String e = getParameter(request, "e");
if (StringUtils.isBlank(e) || Application.getCommonsCache().get(e) == null) {
response.sendError(HttpStatus.FORBIDDEN.value(), getLang(request, "ShardeFileExpired"));
response.sendError(HttpStatus.FORBIDDEN.value(), $L("分享的文件已过期"));
return;
}

View file

@ -27,6 +27,8 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 文件共享
*
@ -51,7 +53,7 @@ public class FileShareController extends BaseController {
public JSON makeSharedFile(HttpServletRequest request) {
Assert.isTrue(
RebuildConfiguration.getBool(ConfigurationItem.FileSharable),
getLang(request, "FileSharableDeny"));
$L("不允许分享文件"));
String fileUrl = getParameterNotNull(request, "url");
int mtime = getIntParameter(request, "time", 5);
@ -65,11 +67,11 @@ public class FileShareController extends BaseController {
@GetMapping("/s/{shareKey}")
public ModelAndView viewSharedFile(@PathVariable String shareKey,
HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpServletResponse response) throws IOException {
String fileUrl;
if (!RebuildConfiguration.getBool(ConfigurationItem.FileSharable)
|| (fileUrl = Application.getCommonsCache().get(shareKey)) == null) {
response.sendError(403, getLang(request, "ShardeFileExpired"));
response.sendError(403, $L("分享的文件已过期"));
return null;
}

View file

@ -29,6 +29,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 文件上传
*
@ -73,7 +75,7 @@ public class FileUploader extends BaseController {
file.transferTo(dest);
if (!dest.exists()) {
writeFailure(response, getLang(request, "ErrorUpload"));
writeFailure(response, $L("上传失败,请稍后重试"));
return;
}
@ -85,7 +87,7 @@ public class FileUploader extends BaseController {
if (uploadName != null) {
writeSuccess(response, uploadName);
} else {
writeFailure(response, getLang(request, "ErrorUpload"));
writeFailure(response, $L("上传失败,请稍后重试"));
}
}

View file

@ -30,6 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 导航菜单设置
*
@ -45,7 +47,7 @@ public class NavSettings extends BaseController implements ShareTo {
final ID user = getRequestUser(request);
RbAssert.isAllow(
Application.getPrivilegesManager().allow(user, ZeroEntry.AllowCustomNav),
getLang(request, "NoOpPrivileges"));
$L("无操作权限"));
ID cfgid = getIdParameter(request, "id");
// 普通用户只能有一个

View file

@ -44,6 +44,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 列表配置
*
@ -60,7 +62,7 @@ public class ShowFieldsController extends BaseController implements ShareTo {
final ID user = getRequestUser(request);
RbAssert.isAllow(
Application.getPrivilegesManager().allow(user, ZeroEntry.AllowCustomDataList),
getLang(request, "NoOpPrivileges"));
$L("无操作权限"));
ID cfgid = getIdParameter(request, "id");
// 普通用户只能有一个

View file

@ -64,7 +64,7 @@ public class ChartDesignController extends EntityController {
final ID user = getRequestUser(request);
RbAssert.isAllow(
Application.getPrivilegesManager().allow(user, ZeroEntry.AllowCustomChart),
getLang(request, "NoOpPrivileges"));
$L("无操作权限"));
ModelAndView mv = createModelAndView("/dashboard/chart-design");

View file

@ -53,7 +53,7 @@ public class BatchUpdateController extends BaseController {
final ID user = getRequestUser(request);
RbAssert.isAllow(
Application.getPrivilegesManager().allow(user, ZeroEntry.AllowBatchUpdate),
getLang(request, "NoOpPrivileges"));
$L("无操作权限"));
JSONObject requestData = (JSONObject) ServletUtils.getRequestJson(request);

View file

@ -89,8 +89,7 @@ public class GeneralOperatingController extends BaseController {
// 检查重复值
List<Record> repeated = ies.getAndCheckRepeated(record, 100);
if (!repeated.isEmpty()) {
return new RespBody(CODE_REPEATED_VALUES,
getLang(request, "RecordRepeated"), buildRepeatedData(repeated));
return new RespBody(CODE_REPEATED_VALUES, $L("存在重复记录"), buildRepeatedData(repeated));
}
try {

View file

@ -69,7 +69,7 @@ public class ModelExtrasController extends BaseController {
RecordTransfomer transfomer = new RecordTransfomer(targetEntity, (JSONObject) config.getJSON("config"));
if (!transfomer.checkFilter(sourceRecord)) {
return RespBody.error(getLang(request, "TransformNotAllow"), 400);
return RespBody.error($L("当前记录不符合转换条件"), 400);
}
ID newId = transfomer.transform(sourceRecord);

View file

@ -24,6 +24,8 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 最近搜索针对引用字段
* 非自动需要调用 <tt>recently-add</tt> 方法手动添加方可用后期考虑自动化
@ -41,7 +43,7 @@ public class RecentlyUsedSearchController extends BaseController {
String type = getParameter(request, "type");
ID[] recently = RecentlyUsedHelper.gets(getRequestUser(request), entity, type);
return formatSelect2(recently, getLang(request, "RecentlyUsed"));
return formatSelect2(recently, $L("最近使用"));
}
@PostMapping("recently-add")

View file

@ -35,6 +35,8 @@ import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 报表/导出
*
@ -83,7 +85,7 @@ public class ReportsController extends BaseController {
final ID user = getRequestUser(request);
RbAssert.isAllow(
Application.getPrivilegesManager().allow(user, ZeroEntry.AllowDataExport),
getLang(request, "NoOpPrivileges"));
$L("无操作权限"));
int dataRange = getIntParameter(request, "dr", BatchOperatorQuery.DR_PAGED);
JSONObject queryData = (JSONObject) ServletUtils.getRequestJson(request);

View file

@ -40,7 +40,7 @@ import java.io.IOException;
import java.util.Date;
import java.util.Set;
import static com.rebuild.core.support.i18n.I18nUtils.$L;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 任务
@ -67,7 +67,7 @@ public class ProjectTaskController extends BaseController {
final ID user = getRequestUser(request);
if (!ProjectHelper.checkReadable(taskId2, user)) {
response.sendError(403, getLang(request, "NoPrivViewTask"));
response.sendError(403, $L("你无权查看此任务"));
return null;
}

View file

@ -61,7 +61,7 @@ public class ApprovalAdminController extends BaseController {
.setParameter(1, configId)
.unique();
if (config == null) {
response.sendError(404, getLang(request, "SomeNotExists", "ApprovalConfig"));
response.sendError(404, $L("审批流程不存在"));
return null;
}

View file

@ -32,6 +32,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author devezhao zhaofang123@gmail.com
* @since 2019/05/23
@ -47,7 +49,7 @@ public class TriggerAdminController extends BaseController {
@GetMapping("trigger/{id}")
public ModelAndView pageEditor(@PathVariable String id,
HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpServletResponse response) throws IOException {
ID configId = ID.valueOf(id);
Object[] config = Application.createQuery(
"select belongEntity,actionType,when,whenFilter,actionContent,priority,name,whenTimer from RobotTriggerConfig where configId = ?")
@ -66,7 +68,7 @@ public class TriggerAdminController extends BaseController {
mv.getModel().put("sourceEntity", sourceEntity.getName());
mv.getModel().put("sourceEntityLabel", EasyMetaFactory.getLabel(sourceEntity));
mv.getModel().put("actionType", actionType.name());
mv.getModel().put("actionTypeLabel", getLang(request, actionType.name()));
mv.getModel().put("actionTypeLabel", $L(actionType.getDisplayName()));
mv.getModel().put("when", config[2]);
mv.getModel().put("whenTimer", config[7] == null ? StringUtils.EMPTY : config[7]);
mv.getModel().put("whenFilter", StringUtils.defaultIfBlank((String) config[3], JSONUtils.EMPTY_OBJECT_STR));
@ -77,10 +79,10 @@ public class TriggerAdminController extends BaseController {
}
@GetMapping("trigger/available-actions")
public List<String[]> getAvailableActions(HttpServletRequest request) {
public List<String[]> getAvailableActions() {
List<String[]> alist = new ArrayList<>();
for (ActionType t : ActionFactory.getAvailableActions()) {
alist.add(new String[] { t.name(), getLang(request, t.name()) });
alist.add(new String[] { t.name(), $L(t.getDisplayName()) });
}
return alist;
}
@ -109,7 +111,7 @@ public class TriggerAdminController extends BaseController {
Object[][] array = ReportTemplateController.queryListOfConfig(sql, belongEntity, q);
for (Object[] o : array) {
o[7] = getLang(request, (String) o[7]);
o[7] = $L(ActionType.valueOf((String) o[7]).getDisplayName());
}
return array;
}

View file

@ -27,6 +27,8 @@ import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 用户设置
*
@ -47,23 +49,23 @@ public class UserSettings extends EntityController {
@RequestMapping("/user/send-email-vcode")
public RespBody sendEmailVcode(HttpServletRequest request) {
if (!SMSender.availableMail()) {
return RespBody.error(getLang(request, "EmailAccountUnset"));
return RespBody.errorl("邮件服务账户未配置,请联系管理员配置");
}
String email = getParameterNotNull(request, "email");
if (Application.getUserStore().existsEmail(email)) {
return RespBody.error(getLang(request, "EmailBeUsed"));
return RespBody.errorl("邮箱已被占用,请换用其他邮箱");
}
String vcode = VerfiyCode.generate(email);
String subject = getLang(request, "EmailVcode");
String content = String.format(getLang(request, "YourVCode", "Email"), vcode);
String subject = "邮箱验证码";
String content = $L("你的邮箱验证码是 : **%s**", vcode);
String sentid = SMSender.sendMail(email, subject, content);
if (sentid != null) {
return RespBody.ok();
} else {
return RespBody.error(getLang(request, "OperationFailed"));
return RespBody.errorl("操作失败,请稍后重试");
}
}
@ -74,11 +76,11 @@ public class UserSettings extends EntityController {
String vcode = getParameterNotNull(request, "vcode");
if (!VerfiyCode.verfiy(email, vcode)) {
return RespBody.error(getLang(request, "SomeInvalid", "Vcode"));
return RespBody.errorl("验证码无效");
}
if (Application.getUserStore().existsEmail(email)) {
return RespBody.error(getLang(request, "EmailBeUsed"));
return RespBody.errorl("邮箱已被占用,请换用其他邮箱");
}
Record record = EntityHelper.forUpdate(user, user);
@ -97,7 +99,7 @@ public class UserSettings extends EntityController {
.setParameter(1, user)
.unique();
if (o == null || !StringUtils.equals((String) o[0], EncryptUtils.toSHA256Hex(oldp))) {
return RespBody.error(getLang(request, "OldPasswdWrong"));
return RespBody.errorl("原密码输入有误");
}
Record record = EntityHelper.forUpdate(user, user);

View file

@ -48,6 +48,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author zhaofang123@gmail.com
* @since 07/25/2018
@ -278,14 +280,14 @@ public class LoginController extends BaseController {
}
String vcode = VerfiyCode.generate(email, 2);
String subject = getLang(request, "ResetPassword");
String content = String.format(getLang(request, "YourVCode", "ResetPassword"), vcode);
String subject = $L("重置密码");
String content = $L("你的重置密码验证码是 : **%s**", vcode);
String sentid = SMSender.sendMail(email, subject, content);
if (sentid != null) {
return RespBody.ok();
} else {
return RespBody.errorl("OperationFailed");
return RespBody.errorl("操作失败,请稍后重试");
}
}

View file

@ -37,6 +37,8 @@ import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* 用户自助注册
*
@ -49,9 +51,9 @@ import java.io.IOException;
public class SignUpController extends BaseController {
@GetMapping("signup")
public ModelAndView pageSignup(HttpServletRequest request, HttpServletResponse response) throws IOException {
public ModelAndView pageSignup(HttpServletResponse response) throws IOException {
if (!RebuildConfiguration.getBool(ConfigurationItem.OpenSignUp)) {
response.sendError(400, getLang(request, "SignupNotOpen"));
response.sendError(400, $L("管理员未开放公开注册"));
return null;
}
return createModelAndView("/signup/signup");
@ -72,8 +74,10 @@ public class SignUpController extends BaseController {
}
String vcode = VerfiyCode.generate(email, 1);
String content = String.format(getLang(request, "YourVCode", "Signup"), vcode);
String sentid = SMSender.sendMail(email, getLang(request, "SignupVcode"), content);
String title = $L("注册验证码");
String content = $L("你的注册验证码是 : **%s**", vcode);
String sentid = SMSender.sendMail(email, title, content);
log.warn(email + " >>>>> " + content);
if (sentid != null) {
@ -109,8 +113,11 @@ public class SignUpController extends BaseController {
// 通知用户
String homeUrl = RebuildConfiguration.getHomeUrl();
String content = String.format(getLang(request, "SignupPending"), fullName, loginName, passwd, homeUrl, homeUrl);
SMSender.sendMail(email, getLang(request, "AdminReviewSignup"), content);
String title = $L("管理员正在审核你的注册信息");
String content = $L(
"%s 欢迎注册!以下是你的注册信息,请妥善保管。 [][] 登录账号 : **%s** [] 登录密码 : **%s** [] 登录地址 : [%s](%s) [][] 目前你还无法登录系统,因为系统管理员正在审核你的注册信息。完成后会通过邮件通知你,请耐心等待。",
fullName, loginName, passwd, homeUrl, homeUrl);
SMSender.sendMail(email, title, content);
return RespBody.ok();

View file

@ -17,6 +17,7 @@ import java.util.regex.Pattern;
/**
* 多语言提取
* 1. .java 文件提取 `$L(xxx)` `errorl(xxx)` 注意不要换行
*
* @author devezhao
* @since 2021/5/14
@ -49,11 +50,11 @@ public class I18nGettextParser {
static void parse(File fileOrDir, Set<String> into) throws IOException {
String fileName = fileOrDir.getName();
if (fileOrDir.isFile()) {
if (fileName.endsWith(".js")) {
if (fileName.endsWith(".jsx")) {
into.addAll(parseJs(fileOrDir));
} else if (fileName.endsWith(".html")) {
} else if (fileName.endsWith(".htmlx")) {
into.addAll(parseHtml(fileOrDir));
} else if (fileName.endsWith(".java")) {
} else if (fileName.endsWith("UserService.java")) {
into.addAll(parseJava(fileOrDir));
}
@ -69,18 +70,23 @@ public class I18nGettextParser {
}
static List<String> parseJs(File file) throws IOException {
Pattern pattern = Pattern.compile("\\$L\\('(\\S+)'\\)");
Pattern pattern = Pattern.compile("\\$L\\('(.*?)'\\)");
return parseWithPattern(file, pattern);
}
static List<String> parseHtml(File file) throws IOException {
Pattern pattern = Pattern.compile("bundle\\.L\\('(\\S+)'\\)");
Pattern pattern = Pattern.compile("bundle\\.L\\('(.*?)'\\)");
return parseWithPattern(file, pattern);
}
static List<String> parseJava(File file) throws IOException {
Pattern pattern = Pattern.compile("\\$L\\(\"(\\S+)\"\\)");
return parseWithPattern(file, pattern);
Pattern pattern = Pattern.compile("\\$L\\(\"(.*?)\"[, \\)]");
List<String> list = new ArrayList<>(parseWithPattern(file, pattern));
pattern = Pattern.compile("errorl\\(\"(.*?)\"[, \\)]");
list.addAll(parseWithPattern(file, pattern));
return list;
}
static List<String> parseWithPattern(File file, Pattern pattern) throws IOException {

View file

@ -8,17 +8,16 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.core.support.i18n;
import cn.devezhao.persist4j.Entity;
import com.alibaba.fastjson.JSON;
import com.rebuild.TestSupport;
import com.rebuild.core.Application;
import com.rebuild.core.configuration.NavBuilder;
import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.metadata.easymeta.DisplayType;
import com.rebuild.core.service.approval.ApprovalState;
import com.rebuild.utils.JSONUtils;
import org.junit.jupiter.api.Test;
import static com.rebuild.core.support.i18n.Language.$L;
/**
* @author devezhao
* @since 2020/8/26
@ -27,27 +26,23 @@ public class LanguageTest extends TestSupport {
@Test
public void getLang() {
System.out.println("Home > " + Language.L("Home"));
System.out.println("AddSome > " + Language.L("AddSome", "Home"));
System.out.println("HasXNotice > " + Language.LF("HasXNotice", 99));
System.out.println($L("首页"));
System.out.println($L("%s首页", "谁的"));
System.out.println($L("%d条数据", 100));
Entity entity = MetadataHelper.getEntity(EntityHelper.User);
System.out.println("e.User > " + Language.L(entity));
System.out.println("f.createdOn > " + Language.L(entity.getField(EntityHelper.CreatedOn)));
System.out.println("f.User.fullName > " + Language.L(entity.getField("fullName")));
System.out.println("s.ApprovalState.PROCESSING > " + Language.L(ApprovalState.PROCESSING));
System.out.println($L(entity));
System.out.println($L(entity.getField(EntityHelper.CreatedOn)));
System.out.println($L(ApprovalState.PROCESSING));
System.out.println($L(DisplayType.ANYREFERENCE));
}
@Test
public void getMdLang() {
System.out.println("Support MD > " + Language.L("SystemFailureMemo"));
}
@Test
public void replaceLangKey() {
JSON resource = NavBuilder.instance.getUserNav(UserService.ADMIN_USER);
resource = Application.getLanguage().getDefaultBundle().replaceLangKey(resource);
System.out.println(JSONUtils.prettyPrint(resource));
System.out.println($L("**加粗**"));
System.out.println($L("换行 [] 第二行"));
System.out.println($L("这是一个 [链接](https://getrebuild.com/)"));
}
@Test