Files
Dynamic-Form-Tools/DevResources/Message.java
skidus 186c729ece refactor: rebrand to DynamicFormTools and add i18n support
- Rebranded plugin from "ActionModelsGenerator" to "Dynamic Form Helper".
- Refactored package structure from "com.sdk.generators" to "com.sdk.dynform.tools".
- Added comprehensive I18n support for Java, XML, and JavaScript:
    - Inlay hints and code folding for internationalization keys.
    - Completion and reference contributors for "message.xml" keys.
    - Configuration settings and UI for i18n tools.
- Introduced support for the ".frml" (DynForm) file type.
- Added specialized DynForm completion and path resolution helpers.
- Updated "build.gradle.kts" with JSP and JavaScript platform dependencies.
- Updated documentation and project metadata to reflect the new name.
2026-04-07 22:39:20 +07:00

275 lines
7.5 KiB
Java
Executable File

package sdk.i18n;
import com.apps.Constants;
import com.apps.SystemFactory;
import jakarta.servlet.ServletContext;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import sdk.config.ApiConfig;
import sdk.json.JSONObject;
import sdk.context.AppContext;
import sdk.utils.JUtils;
import sdk.utils.SDKLogger;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
public class Message {
private LinkedHashMap<String, LinkedHashMap<String, String>> msgMaps;
private SystemFactory system;
private LinkedHashMap<String, String> rescMessage;
private final SDKLogger logger;
public Message() {
rescMessage = new LinkedHashMap<>();
logger = new SDKLogger("i18N-Message");
}
public Message(SystemFactory factory) {
this.system = factory;
AppContext app = factory.getAppInstance();
logger = new SDKLogger("i18N-Message");
msgMaps = (LinkedHashMap<String, LinkedHashMap<String, String>>) app.getAttribute(Constants._APP_MESSAGE);
if (msgMaps != null) {
for (String key : msgMaps.keySet()) {
if (msgMaps.get(key) == null) {
msgMaps = null;
break;
}
}
}
if (msgMaps == null || msgMaps.isEmpty() || msgMaps.containsValue(null)) {
msgMaps = new LinkedHashMap<>();
ApiConfig msgAPI = factory.getApi("i18n");
for (ApiConfig.ApiParameter param : msgAPI.getParameters().values()) {
String rescFile = param.getValue();
if (!"".equals(rescFile)) {
LinkedHashMap<String, String> rescMsg = readResource(rescFile);
String lang = param.getName().toUpperCase();
msgMaps.put(lang, rescMsg);
}
}
app.setAttribute(Constants._APP_MESSAGE, msgMaps);
}
String lang = factory.getLanguage("TH");
rescMessage = msgMaps.get(lang.toUpperCase());
if (rescMessage == null) {
rescMessage = msgMaps.get("TH");
}
}
public LinkedHashMap<String,String> getLang(String lang) {
return msgMaps.get(lang.toUpperCase());
}
public String parseExp(String inStr) {
String result = inStr;
// String[] ssnToken = JUtils.getRegxToken(inStr, "@\\{[\\s\\S]+?\\}");
// int idxFactor = 2;
// if (ssnToken.length > 0) {
// DTO_SYSTEM_CONFIG sysData= system.getSysData();
// for (String token : ssnToken) {
// String ssnKey = token.substring(0, token.length() - 1).substring(idxFactor).trim();
// String ssnValue = sysData.getValue(ssnKey, "");
// if (!ssnValue.isBlank()) {
// result = result.replace(token, ssnValue);
// }
// }
// }
String[] ssnToken = JUtils.getRegxToken(result, "@[M]\\{[\\s\\S]+?\\}");
int idxFactor = 3;
for (String token : ssnToken) {
String msgKey = token.substring(0, token.length() - 1).substring(idxFactor).trim();
result = result.replace(token, this.get(msgKey));
}
return result.replaceAll("\\|\\|","");
}
private LinkedHashMap<String, String> readResource(String fileName) {
LinkedHashMap<String, String> result = new LinkedHashMap<>();
SAXBuilder formBuilder = new SAXBuilder();
formBuilder.setFeature("http://xml.org/sax/features/validation", false);
formBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
formBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
ServletContext context = system.getAppContext();
InputStream rescFile = context.getResourceAsStream(fileName);
try {
Document rescDoc = formBuilder.build(rescFile);
Element rescRoot = rescDoc.getRootElement();
List<Element> msgList = rescRoot.getChildren("entry");
for (Element elMsg : msgList) {
String key = elMsg.getAttributeValue("key", "");
String value = elMsg.getTextTrim();
if (!"".equals(key)) {
value = parseExp(value);
result.put(key.toLowerCase(), value);
}
}
} catch (Exception ex) {
result = null;
logger.error(ex);
}
return result;
}
public String get(String key, String locale) {
if (key.startsWith("#")) {
return key.substring(1);
}
LinkedHashMap<String,String> message = null;
if (locale != null) {
message = getLang(locale.toUpperCase());
}
if (message == null) {
message = rescMessage;
}
if (!message.isEmpty()) {
boolean useDot = false;
String msgKey = key.replaceAll("-", "_").toLowerCase();
String[] keys = msgKey.split(" ");
if (keys.length == 1) {
keys = msgKey.split("\\+");
useDot = keys.length > 1;
}
String result;
if (keys.length > 1) {
result = msgKey;
int seq = 0;
for (String id : keys) {
if (id.isBlank()) continue;
String value = message.get(id);
if (value != null) {
result = result.replace((seq > 0 && useDot) ? "+" + id : id, value);
} else {
value = this.get(id,locale);
result = result.replace(id, value);
}
seq++;
}
} else {
result = message.get(msgKey.toLowerCase());
if (result == null) {
result = JUtils.beautify(msgKey.replace("_", " "));
}
}
return result;
} else {
return key;
}
}
public String get(String key) {
if (key.startsWith("#")||key.startsWith("=")) {
return key.substring(1);
}
if (!rescMessage.isEmpty()) {
boolean useDot = false;
String msgKey = key.toLowerCase();
String[] keys = key.split(" ");
if (keys.length == 1) {
keys = msgKey.split("\\+");
useDot = keys.length > 1;
}
if (keys.length == 1) {
keys = msgKey.split("\\|\\|");
}
String result;
if (keys.length > 1) {
result = msgKey;
int seq = 0;
for (String id : keys) {
String value;
String idKey = id;
if (id.isBlank()) continue;
id = id.replaceAll("-", "_").toLowerCase();
if (idKey.startsWith("#")) {
result = result.replace(id, idKey.substring(1));
} else {
if (!id.equals("-")) {
value = rescMessage.get(id);
} else {
value = "-";
}
if (value != null) {
result = result.replace((seq > 0 && useDot) ? "+" + id : id, value);
} else {
value = this.get(id);
result = result.replace((seq > 0 && useDot) ? "+" + id : id, value);
result = result.replace(id, value);
}
}
seq ++;
}
} else {
msgKey = key.replaceAll("-","_").toLowerCase();
result = rescMessage.get(msgKey.toLowerCase());
if (result == null) {
if (!msgKey.contains(".")) {
result = rescMessage.get("sys."+msgKey.toLowerCase());
} else {
result = msgKey.substring(msgKey.indexOf(".")+1);
if (result.isBlank()) {
result = msgKey;
}
result = JUtils.beautify(result.replace("_", " "));
}
result = (result == null) ? JUtils.beautify(msgKey.replace("_", " ")) : result;
}
}
return result.replaceAll("\\|\\|","");
} else {
return key;
}
}
public String buildJson(String lang) {
LinkedHashMap<String, String> langMsg = msgMaps.get(lang.toUpperCase());
if (langMsg == null) {
msgMaps.get("TH");
}
JSONObject jsResult = new JSONObject();
SortedSet<String> keys = new TreeSet<>(langMsg.keySet());
for (String key : keys) {
String value = langMsg.get(key);
jsResult.put(key,value);
}
return jsResult.toString();
}
public String buildObject(String lang) {
LinkedHashMap<String, String> langMsg = msgMaps.get(lang.toUpperCase());
if (langMsg == null) {
langMsg = msgMaps.get("TH");
}
if (langMsg == null) {
langMsg = msgMaps.firstEntry().getValue();
}
JSONObject jsResult = new JSONObject();
langMsg.forEach(jsResult::put);
return jsResult.toString(4);
}
}