Initial project
This commit is contained in:
128
.gitignore
vendored
128
.gitignore
vendored
@ -1,98 +1,38 @@
|
|||||||
# ---> JetBrains
|
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
||||||
|
|
||||||
# User-specific stuff
|
|
||||||
.idea/**/workspace.xml
|
|
||||||
.idea/**/tasks.xml
|
|
||||||
.idea/**/usage.statistics.xml
|
|
||||||
.idea/**/dictionaries
|
|
||||||
.idea/**/shelf
|
|
||||||
|
|
||||||
# AWS User-specific
|
|
||||||
.idea/**/aws.xml
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
.idea/**/contentModel.xml
|
|
||||||
|
|
||||||
# Sensitive or high-churn files
|
|
||||||
.idea/**/dataSources/
|
|
||||||
.idea/**/dataSources.ids
|
|
||||||
.idea/**/dataSources.local.xml
|
|
||||||
.idea/**/sqlDataSources.xml
|
|
||||||
.idea/**/dynamic.xml
|
|
||||||
.idea/**/uiDesigner.xml
|
|
||||||
.idea/**/dbnavigator.xml
|
|
||||||
|
|
||||||
# Gradle
|
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
|
||||||
|
|
||||||
# Gradle and Maven with auto-import
|
|
||||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
||||||
# since they will be recreated, and may cause churn. Uncomment if using
|
|
||||||
# auto-import.
|
|
||||||
# .idea/artifacts
|
|
||||||
# .idea/compiler.xml
|
|
||||||
# .idea/jarRepositories.xml
|
|
||||||
# .idea/modules.xml
|
|
||||||
# .idea/*.iml
|
|
||||||
# .idea/modules
|
|
||||||
# *.iml
|
|
||||||
# *.ipr
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# Mongo Explorer plugin
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
|
|
||||||
# File-based project format
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
out/
|
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
|
||||||
.idea_modules/
|
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# SonarLint plugin
|
|
||||||
.idea/sonarlint/
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
|
|
||||||
# Editor-based Rest Client
|
|
||||||
.idea/httpRequests
|
|
||||||
|
|
||||||
# Android studio 3.1+ serialized cache file
|
|
||||||
.idea/caches/build_file_checksums.ser
|
|
||||||
|
|
||||||
# ---> Maven
|
|
||||||
target/
|
target/
|
||||||
pom.xml.tag
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
pom.xml.releaseBackup
|
!**/src/main/**/target/
|
||||||
pom.xml.versionsBackup
|
!**/src/test/**/target/
|
||||||
pom.xml.next
|
|
||||||
release.properties
|
|
||||||
dependency-reduced-pom.xml
|
|
||||||
buildNumber.properties
|
|
||||||
.mvn/timing.properties
|
|
||||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
|
||||||
.mvn/wrapper/maven-wrapper.jar
|
|
||||||
|
|
||||||
# Eclipse m2e generated files
|
### IntelliJ IDEA ###
|
||||||
# Eclipse Core
|
.idea/modules.xml
|
||||||
.project
|
.idea/jarRepositories.xml
|
||||||
# JDT-specific (Eclipse Java Development Tools)
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
.classpath
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Palette2">
|
||||||
|
<group name="Swing">
|
||||||
|
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Button" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="RadioButton" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="CheckBox" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Label" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||||
|
<preferred-size width="-1" height="20" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
</group>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
47
pom.xml
Normal file
47
pom.xml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.imyeyu.lang</groupId>
|
||||||
|
<artifactId>timi-lang</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.test.skip>true</maven.test.skip>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.11.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>21</source>
|
||||||
|
<target>21</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imyeyu.io</groupId>
|
||||||
|
<artifactId>timi-io</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
|
<version>3.5.3</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.imyeyu.lang.mapper;
|
||||||
|
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
import com.imyeyu.java.bean.LanguageMapping;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-01 16:25
|
||||||
|
*/
|
||||||
|
public abstract class AbstractLanguageMapper implements LanguageMapping {
|
||||||
|
|
||||||
|
protected static final MessageFormat FORMAT = new MessageFormat("");
|
||||||
|
|
||||||
|
protected final Language language;
|
||||||
|
|
||||||
|
protected boolean isDebugging = false;
|
||||||
|
|
||||||
|
public AbstractLanguageMapper(Language language) {
|
||||||
|
this.language = language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Language getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugging(boolean debugging) {
|
||||||
|
isDebugging = debugging;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/main/java/com/imyeyu/lang/mapper/FileLanguageMap.java
Normal file
35
src/main/java/com/imyeyu/lang/mapper/FileLanguageMap.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package com.imyeyu.lang.mapper;
|
||||||
|
|
||||||
|
import com.imyeyu.io.IO;
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-09 01:00
|
||||||
|
*/
|
||||||
|
public class FileLanguageMap extends PropertiesLanguageMap {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认构造
|
||||||
|
*
|
||||||
|
* @param language 所属语言
|
||||||
|
*/
|
||||||
|
public FileLanguageMap(Language language) {
|
||||||
|
super(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String path) {
|
||||||
|
try {
|
||||||
|
InputStream is = IO.getInputStream(path.formatted(language.toString()));
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(new InputStreamReader(is));
|
||||||
|
load(properties);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("load language properties file error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/main/java/com/imyeyu/lang/mapper/LanguageMap.java
Normal file
124
src/main/java/com/imyeyu/lang/mapper/LanguageMap.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package com.imyeyu.lang.mapper;
|
||||||
|
|
||||||
|
import com.imyeyu.java.TimiJava;
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
import com.imyeyu.utils.Text;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-03 10:11
|
||||||
|
*/
|
||||||
|
public class LanguageMap extends AbstractLanguageMapper {
|
||||||
|
|
||||||
|
protected final Map<String, String> map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认构造
|
||||||
|
*
|
||||||
|
* @param language 所属语言
|
||||||
|
*/
|
||||||
|
public LanguageMap(Language language) {
|
||||||
|
super(language);
|
||||||
|
this.map = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void union(LanguageMap map) {
|
||||||
|
this.map.putAll(map.map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(String key, String value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(String key) {
|
||||||
|
return map.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文本,支持二次映射,没有找到映射时返回入参键
|
||||||
|
* <pre>
|
||||||
|
* test.msg=Hello world
|
||||||
|
* mapping=@test.msg
|
||||||
|
* no_mapping=\@test.msg
|
||||||
|
*
|
||||||
|
* Multilingual.text("mapping"); // Hello world
|
||||||
|
* Multilingual.text("no_mapping"); // @test.msg
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return 文本值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String text(String key) {
|
||||||
|
if (map.containsKey(key)) {
|
||||||
|
String result = map.get(key);
|
||||||
|
if (result.startsWith("@")) {
|
||||||
|
// 递归映射
|
||||||
|
return text(result.substring(1));
|
||||||
|
} else {
|
||||||
|
if (result.startsWith("\\@")) {
|
||||||
|
return result.substring(1);
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (TimiJava.isNotEmpty(key)) {
|
||||||
|
// 推测
|
||||||
|
String guessKey = key;
|
||||||
|
LinkedHashMap<String, Number> keySRL = Text.similarityRatioList(map.keySet(), key);
|
||||||
|
if (keySRL.keySet().iterator().hasNext()) {
|
||||||
|
String k = keySRL.keySet().iterator().next();
|
||||||
|
Number ratio = keySRL.get(k);
|
||||||
|
if (.7 < ratio.doubleValue()) {
|
||||||
|
guessKey = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.err.printf("not found language mapping for key: [%s], it is [%s]?%n", key, guessKey);
|
||||||
|
if (isDebugging) {
|
||||||
|
throw new RuntimeException("not found language mapping key: " + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 找不到映射,直接返回键
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文本
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param def 默认值(没有找到映射值时)
|
||||||
|
* @return 获取结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String text(String key, String def) {
|
||||||
|
String result = text(key);
|
||||||
|
return key.equals(result) ? def : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入参数获取文本
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param args 参数
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String textArgs(String key, Object... args) {
|
||||||
|
String result = text(key);
|
||||||
|
if (map.containsKey(result)) {
|
||||||
|
// 没有映射值
|
||||||
|
return result + Arrays.toString(args);
|
||||||
|
}
|
||||||
|
FORMAT.applyPattern(result);
|
||||||
|
return FORMAT.format(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.imyeyu.lang.mapper;
|
||||||
|
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-09 00:50
|
||||||
|
*/
|
||||||
|
public class PropertiesLanguageMap extends LanguageMap {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认构造
|
||||||
|
*
|
||||||
|
* @param language 所属语言
|
||||||
|
*/
|
||||||
|
public PropertiesLanguageMap(Language language) {
|
||||||
|
super(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public void load(Properties properties) {
|
||||||
|
map.putAll(new HashMap(properties));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.imyeyu.lang.mapper;
|
||||||
|
|
||||||
|
import com.imyeyu.io.IO;
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-09 00:55
|
||||||
|
*/
|
||||||
|
public class ResourcesLanguageMap extends PropertiesLanguageMap {
|
||||||
|
/**
|
||||||
|
* 默认构造
|
||||||
|
*
|
||||||
|
* @param language 所属语言
|
||||||
|
*/
|
||||||
|
public ResourcesLanguageMap(Language language) {
|
||||||
|
super(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(String path) {
|
||||||
|
try {
|
||||||
|
InputStream is = IO.resourceToInputStream(getClass(), path.formatted(language.toString()));
|
||||||
|
if (is != null) {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(new InputStreamReader(is));
|
||||||
|
load(properties);
|
||||||
|
} else {
|
||||||
|
throw new FileNotFoundException("not found language properties file: " + path.formatted(language.toString()));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("load language properties file error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/com/imyeyu/lang/multi/FileMultilingual.java
Normal file
29
src/main/java/com/imyeyu/lang/multi/FileMultilingual.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package com.imyeyu.lang.multi;
|
||||||
|
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
import com.imyeyu.lang.mapper.AbstractLanguageMapper;
|
||||||
|
import com.imyeyu.lang.mapper.FileLanguageMap;
|
||||||
|
import com.imyeyu.lang.mapper.LanguageMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-09 01:06
|
||||||
|
*/
|
||||||
|
public class FileMultilingual extends Multilingual {
|
||||||
|
|
||||||
|
public void addAll(String path) {
|
||||||
|
Language[] values = Language.values();
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
FileLanguageMap mapper = new FileLanguageMap(values[i]);
|
||||||
|
mapper.load(path);
|
||||||
|
if (multilingualMap.containsKey(values[i])) {
|
||||||
|
AbstractLanguageMapper existMapper = multilingualMap.get(values[i]);
|
||||||
|
if (existMapper instanceof LanguageMap map) {
|
||||||
|
map.union(mapper);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add(values[i], mapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
218
src/main/java/com/imyeyu/lang/multi/Multilingual.java
Normal file
218
src/main/java/com/imyeyu/lang/multi/Multilingual.java
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
package com.imyeyu.lang.multi;
|
||||||
|
|
||||||
|
import com.imyeyu.java.bean.CallbackArg;
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
import com.imyeyu.java.bean.LanguageMapping;
|
||||||
|
import com.imyeyu.java.ref.Ref;
|
||||||
|
import com.imyeyu.lang.mapper.AbstractLanguageMapper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多语言系统,支持多文件多语言加载
|
||||||
|
* <pre>
|
||||||
|
* // lang 文件
|
||||||
|
* say.msg=hello {0}
|
||||||
|
*
|
||||||
|
* // 加载
|
||||||
|
* Multilingual lang = Multilingual.getInstance();
|
||||||
|
* lang.load(Language.zh_CN, "lang/timijava/%s.lang");
|
||||||
|
*
|
||||||
|
* // 加载所有支持的映射文件
|
||||||
|
* lang.loadAll("lang/timifx/%s.lang");
|
||||||
|
*
|
||||||
|
* // 设置当前激活语言
|
||||||
|
* lang.setActivated("zh_CN");
|
||||||
|
*
|
||||||
|
* // 引用当前激活语言
|
||||||
|
* Multilingual.text("say.msg");
|
||||||
|
* Multilingual.text("say.msg", "timi-java");
|
||||||
|
*
|
||||||
|
* // 动态引用
|
||||||
|
* Multilingual.map("en_US").text("say.msg");
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2021-10-25 15:16
|
||||||
|
*/
|
||||||
|
public class Multilingual implements LanguageMapping {
|
||||||
|
|
||||||
|
protected final Map<Language, AbstractLanguageMapper> multilingualMap;
|
||||||
|
protected final List<CallbackArg<Language>> updateActiveListeners;
|
||||||
|
|
||||||
|
/** 当前激活语言 */
|
||||||
|
protected Language activated;
|
||||||
|
|
||||||
|
protected boolean isDebugging = false;
|
||||||
|
|
||||||
|
public Multilingual() {
|
||||||
|
multilingualMap = new HashMap<>();
|
||||||
|
updateActiveListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
activated = Ref.toType(Language.class, Locale.getDefault().toString());
|
||||||
|
|
||||||
|
if (activated == null) {
|
||||||
|
activated = Language.zh_CN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Language language, AbstractLanguageMapper mapper) {
|
||||||
|
mapper.setDebugging(isDebugging);
|
||||||
|
multilingualMap.put(language, mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加更新激活语言回调
|
||||||
|
*
|
||||||
|
* @param callback 回调
|
||||||
|
*/
|
||||||
|
public void addUpdateActiveListeners(CallbackArg<Language> callback) {
|
||||||
|
updateActiveListeners.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除更新激活语言回调
|
||||||
|
*
|
||||||
|
* @param callback 回调
|
||||||
|
*/
|
||||||
|
public void removeUpdateActiveListeners(CallbackArg<Language> callback) {
|
||||||
|
updateActiveListeners.remove(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置激活语言
|
||||||
|
*
|
||||||
|
* @param languageName 激活语言
|
||||||
|
*/
|
||||||
|
public void setActivated(String languageName) {
|
||||||
|
setActivated(Ref.toType(Language.class, languageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置激活语言
|
||||||
|
*
|
||||||
|
* @param activated 激活语言
|
||||||
|
*/
|
||||||
|
public void setActivated(Language activated) {
|
||||||
|
Objects.requireNonNull(activated);
|
||||||
|
this.activated = activated;
|
||||||
|
|
||||||
|
String[] localSp = activated.toString().split("_");
|
||||||
|
Locale.setDefault(new Locale(localSp[0], localSp[1]));
|
||||||
|
|
||||||
|
for (int i = 0; i < updateActiveListeners.size(); i++) {
|
||||||
|
updateActiveListeners.get(i).handler(activated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Language getActivated() {
|
||||||
|
return activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugging(boolean debugging) {
|
||||||
|
isDebugging = debugging;
|
||||||
|
for (Map.Entry<Language, AbstractLanguageMapper> item : multilingualMap.entrySet()) {
|
||||||
|
item.getValue().setDebugging(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定映射数据
|
||||||
|
*
|
||||||
|
* @param lang 语言
|
||||||
|
* @return 映射表
|
||||||
|
*/
|
||||||
|
public AbstractLanguageMapper map(String lang) {
|
||||||
|
Language language = Ref.toType(Language.class, lang);
|
||||||
|
if (language == null) {
|
||||||
|
throw new RuntimeException("not support language: " + lang);
|
||||||
|
}
|
||||||
|
return map(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定映射数据
|
||||||
|
*
|
||||||
|
* @param lang 语言
|
||||||
|
* @return 映射表
|
||||||
|
*/
|
||||||
|
public AbstractLanguageMapper map(Language lang) {
|
||||||
|
return multilingualMap.get(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(String key, String value) {
|
||||||
|
multilingualMap.get(getActivated()).add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前激活语言是否存在语言映射
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return true 为存在
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean has(String key) {
|
||||||
|
if (multilingualMap.get(getActivated()) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return multilingualMap.get(getActivated()).has(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从当前激活语言获取文本,支持二次映射,没有找到映射时返回入参键
|
||||||
|
* <pre>
|
||||||
|
* test.msg=Hello world
|
||||||
|
* mapping=@test.msg
|
||||||
|
* no_mapping=\@test.msg
|
||||||
|
*
|
||||||
|
* Multilingual.text("mapping"); // Hello world
|
||||||
|
* Multilingual.text("no_mapping"); // @test.msg
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return 文本值
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String text(String key) {
|
||||||
|
if (multilingualMap.get(getActivated()) == null) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return multilingualMap.get(getActivated()).text(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从当前激活语言获取文本
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param def 默认值(没有找到映射值时)
|
||||||
|
* @return 获取结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String text(String key, String def) {
|
||||||
|
if (multilingualMap.get(getActivated()) == null) {
|
||||||
|
return Objects.requireNonNullElse(def, key);
|
||||||
|
}
|
||||||
|
return multilingualMap.get(getActivated()).text(key, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从当前激活语言获取插入参数文本
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param params 参数
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String textArgs(String key, Object... params) {
|
||||||
|
if (multilingualMap.get(getActivated()) == null) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return multilingualMap.get(getActivated()).textArgs(key, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.imyeyu.lang.multi;
|
||||||
|
|
||||||
|
import com.imyeyu.java.bean.Language;
|
||||||
|
import com.imyeyu.lang.mapper.AbstractLanguageMapper;
|
||||||
|
import com.imyeyu.lang.mapper.LanguageMap;
|
||||||
|
import com.imyeyu.lang.mapper.ResourcesLanguageMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 夜雨
|
||||||
|
* @version 2024-04-09 01:03
|
||||||
|
*/
|
||||||
|
public class ResourcesMultilingual extends Multilingual {
|
||||||
|
|
||||||
|
public void addAll(String path) {
|
||||||
|
Language[] values = Language.values();
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
ResourcesLanguageMap mapper = new ResourcesLanguageMap(values[i]);
|
||||||
|
mapper.load(path);
|
||||||
|
if (multilingualMap.containsKey(values[i])) {
|
||||||
|
AbstractLanguageMapper existMapper = multilingualMap.get(values[i]);
|
||||||
|
if (existMapper instanceof LanguageMap map) {
|
||||||
|
map.union(mapper);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add(values[i], mapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user