From 2f78ab6632b44f0dfbf80101d8501a61684433f8 Mon Sep 17 00:00:00 2001 From: songdragon Date: Sun, 27 Aug 2023 16:37:13 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20#I7W8LM=20=E5=9B=BD=E9=99=85?= =?UTF-8?q?=E5=8C=96=E5=92=8C=E6=9C=AC=E5=9C=B0=E5=8C=96=E4=BD=BF=E7=94=A8?= =?UTF-8?q?i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/encodings.xml | 7 + src/main/java/org/jcnc/jnotepad/LunchApp.java | 4 +- .../jnotepad/app/config/GlobalConfig.java | 1 + .../app/config/LocalizationConfig.java | 303 ++---------------- .../jnotepad/app/i18n/UIResourceBundle.java | 79 +++++ .../jnotepad/app/init/LoadJnotepadConfig.java | 1 - .../jnotepad/app/init/LoadLanguageConfig.java | 6 +- .../jnotepad/constants/TextConstants.java | 8 +- .../controller/event/handler/NewFile.java | 5 +- .../controller/manager/Controller.java | 4 +- .../jcnc/jnotepad/tool/EncodingDetector.java | 6 +- .../jnotepad/ui/menu/JNotepadMenuBar.java | 81 +++-- .../jnotepad/ui/status/JNotepadStatusBox.java | 48 ++- src/main/resources/i18n/i18n.properties | 21 ++ src/main/resources/i18n/i18n_en.properties | 21 ++ src/main/resources/i18n/i18n_zh_CN.properties | 21 ++ 16 files changed, 298 insertions(+), 318 deletions(-) create mode 100644 .idea/encodings.xml create mode 100644 src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java create mode 100644 src/main/resources/i18n/i18n.properties create mode 100644 src/main/resources/i18n/i18n_en.properties create mode 100644 src/main/resources/i18n/i18n_zh_CN.properties diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..106fade --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index 9b16a84..863a9e6 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -9,10 +9,12 @@ import javafx.scene.image.Image; import javafx.scene.layout.Pane; import javafx.stage.Stage; import org.jcnc.jnotepad.app.config.LocalizationConfig; +import org.jcnc.jnotepad.app.i18n.UIResourceBundle; import org.jcnc.jnotepad.app.init.LoadJnotepadConfig; import org.jcnc.jnotepad.app.init.LoadLanguageConfig; import org.jcnc.jnotepad.app.init.LoadShortcutKeyConfig; import org.jcnc.jnotepad.constants.AppConstants; +import org.jcnc.jnotepad.constants.TextConstants; import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.manager.ThreadPoolManager; import org.jcnc.jnotepad.ui.LineNumberTextArea; @@ -82,7 +84,7 @@ public class LunchApp extends Application { viewManager.initScreen(scene); // 加载配置文件 View.getInstance().initJnotepadConfigs(LOAD_JNOTEPAD_CONFIGS); - primaryStage.setTitle(localizationConfig.getTitle()); + UIResourceBundle.bindStringProperty(primaryStage.titleProperty(), TextConstants.TITLE); primaryStage.setWidth(width); primaryStage.setHeight(length); primaryStage.setScene(scene); diff --git a/src/main/java/org/jcnc/jnotepad/app/config/GlobalConfig.java b/src/main/java/org/jcnc/jnotepad/app/config/GlobalConfig.java index fbaaa51..bd4c16c 100644 --- a/src/main/java/org/jcnc/jnotepad/app/config/GlobalConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/config/GlobalConfig.java @@ -31,4 +31,5 @@ public class GlobalConfig { public static GlobalConfig getConfig() { return APP_GLOBAL_CONFIG; } + } diff --git a/src/main/java/org/jcnc/jnotepad/app/config/LocalizationConfig.java b/src/main/java/org/jcnc/jnotepad/app/config/LocalizationConfig.java index 17c7861..62a1735 100644 --- a/src/main/java/org/jcnc/jnotepad/app/config/LocalizationConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/config/LocalizationConfig.java @@ -1,12 +1,13 @@ package org.jcnc.jnotepad.app.config; import org.jcnc.jnotepad.LunchApp; +import org.jcnc.jnotepad.app.i18n.UIResourceBundle; import org.jcnc.jnotepad.tool.LogUtil; import org.slf4j.Logger; import java.io.*; import java.nio.charset.StandardCharsets; -import java.util.Properties; +import java.util.*; import static org.jcnc.jnotepad.constants.AppConstants.APP_NAME; import static org.jcnc.jnotepad.constants.TextConstants.*; @@ -14,300 +15,58 @@ import static org.jcnc.jnotepad.constants.TextConstants.*; /** * 本地化配置文件
* 注意:该配置文件必须先于快捷键配置文件加载 - * @see LunchApp + * * @author gewuyou + * @see LunchApp */ public class LocalizationConfig { - Logger logger = LogUtil.getLogger(this.getClass()); private static final LocalizationConfig LOCALIZATION_CONFIG = new LocalizationConfig(); private final Properties properties = new Properties(); - /** - * 本地化语言包名,默认英文 - */ - private String languagePackName = EN_LANGUAGE_PACK_NAME; + private String language; - private LocalizationConfig() { + private static final Map SUPPORT_LOCALES; + private static final Map SUPPORT_LANGUAGES; - } + static { + Locale.setDefault(Locale.ENGLISH); + SUPPORT_LOCALES = new LinkedHashMap<>(); + SUPPORT_LOCALES.put(CHINESE, Locale.CHINESE); + SUPPORT_LOCALES.put(ENGLISH, Locale.ENGLISH); - /** - * 初始化本地化语言包 - * - * @since 2023/8/25 18:18 - */ - public void initLocalizationConfig() { - // 设置语言包 - try (InputStream inputStream = new FileInputStream(languagePackName)) { - // 使用 UTF-8 编码 - InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); - properties.load(reader); - } catch (IOException e) { - logger.info("未检测到本地化语言包!"); - // 如果读取出错,则调用初始化方法 - initializePropertiesFile(); - } - logger.info("初始化本地化语言包成功!"); - title = properties.getProperty(TITLE, APP_NAME); - sava = properties.getProperty(SAVE); - file = properties.getProperty(FILE); - newly = properties.getProperty(NEW); - open = properties.getProperty(OPEN); - savaAs = properties.getProperty(SAVE_AS); - set = properties.getProperty(SET); - wordWrap = properties.getProperty(WORD_WRAP); - plugin = properties.getProperty(PLUGIN); - addPlugin = properties.getProperty(ADD_PLUGIN); - statistics = properties.getProperty(STATISTICS); - openConfigurationFile = properties.getProperty(OPEN_CONFIGURATION_FILE); - top = properties.getProperty(TOP); - language = properties.getProperty(LANGUAGE); - chinese = properties.getProperty(UPPER_CHINESE); - english = properties.getProperty(UPPER_ENGLISH); - textWrap = properties.getProperty(TEXT_WRAP, "true"); - newFile = properties.getProperty(NEW_FILE); - unknown = properties.getProperty(UNKNOWN); - row = properties.getProperty(ROW); - column = properties.getProperty(COLUMN); - wordCount = properties.getProperty(WORD_COUNT); - encode = properties.getProperty(ENCODE); + SUPPORT_LANGUAGES = new HashMap<>(); + SUPPORT_LANGUAGES.put(Locale.CHINESE, CHINESE); + SUPPORT_LANGUAGES.put(Locale.ENGLISH, ENGLISH); } - /** - * 初始化属性配置文件。 - * 如果属性文件不存在,将创建一个新的属性文件并设置默认属性。 - */ - public void initializePropertiesFile() { - switch (languagePackName) { - case CH_LANGUAGE_PACK_NAME -> { - setChineseLanguagePack(); - createLanguagePacks(languagePackName, properties); - } - case EN_LANGUAGE_PACK_NAME -> { - setEnglishLanguagePack(); - createLanguagePacks(languagePackName, properties); - } - default -> logger.error("语言包加载错误!"); - } + public static final Locale getCurrentLocal() { + return Locale.getDefault(); + } + public static final void setCurrentLocal(Locale locale) { + Locale.setDefault(locale); + UIResourceBundle.getInstance().resetLocal(); + LOCALIZATION_CONFIG.setLanguage(SUPPORT_LANGUAGES.get(locale)); } - private void createLanguagePacks(String languagePackName, Properties languagePack) { - try (OutputStream outputStream = new FileOutputStream(languagePackName)) { - // 使用 UTF-8 编码 - OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8); - languagePack.store(writer, languagePackName); - } catch (IOException ignored) { - logger.info("未检测到语言包!"); + public static final void setCurrentLocal(String language) { + Locale locale = SUPPORT_LOCALES.get(language); + if (locale != null) { + setCurrentLocal(locale); } } - private void setChineseLanguagePack() { - properties.clear(); - // 设置默认属性 - properties.setProperty(TITLE, APP_NAME); - properties.setProperty(NEW_FILE, "新建文件"); - properties.setProperty(SAVE, "保存"); - properties.setProperty(FILE, "文件"); - properties.setProperty(NEW, "新建"); - properties.setProperty(OPEN, "打开"); - properties.setProperty(SAVE_AS, "另存为"); - properties.setProperty(SET, "设置"); - properties.setProperty(WORD_WRAP, "自动换行"); - properties.setProperty(OPEN_CONFIGURATION_FILE, "打开配置文件"); - properties.setProperty(PLUGIN, "插件"); - properties.setProperty(ADD_PLUGIN, "增加插件"); - properties.setProperty(STATISTICS, "统计字数"); - properties.setProperty(ROW, "行数"); - properties.setProperty(COLUMN, "列数"); - properties.setProperty(WORD_COUNT, "字数"); - properties.setProperty(ENCODE, "编码"); - properties.setProperty(TOP, "窗口置顶"); - properties.setProperty(LANGUAGE, "语言"); - properties.setProperty(UPPER_CHINESE, "中文"); - properties.setProperty(UPPER_ENGLISH, "英文"); - } + private LocalizationConfig() { - private void setEnglishLanguagePack() { - properties.clear(); - properties.setProperty(TITLE, APP_NAME); - properties.setProperty(NEW_FILE, "New File"); - properties.setProperty(SAVE, "Save"); - properties.setProperty(FILE, "File"); - properties.setProperty(NEW, "New"); - properties.setProperty(OPEN, "Open"); - properties.setProperty(SAVE_AS, "Save As"); - properties.setProperty(SET, "Settings"); - properties.setProperty(WORD_WRAP, "Word Wrap"); - properties.setProperty(OPEN_CONFIGURATION_FILE, "Open Configuration File"); - properties.setProperty(PLUGIN, "Plugins"); - properties.setProperty(ADD_PLUGIN, "Add Plugin"); - properties.setProperty(STATISTICS, "Word Count"); - properties.setProperty(ROW, "Row"); - properties.setProperty(COLUMN, "Column"); - properties.setProperty(WORD_COUNT, "Word Count"); - properties.setProperty(ENCODE, "Encoding"); - properties.setProperty(TOP, "Window Top"); - properties.setProperty(LANGUAGE, "Language"); - properties.setProperty(UPPER_CHINESE, "Chinese"); - properties.setProperty(UPPER_ENGLISH, "English"); } private String textWrap; - /// 应用程序文本 - - private String title; - - ///菜单栏文本 - - private String sava; - - private String file; - - private String newly; - - private String open; - - private String savaAs; - - private String set; - - private String wordWrap; - - private String plugin; - - private String addPlugin; - - private String statistics; - private String openConfigurationFile; - - private String top; - - private String language; - - private String chinese; - - private String english; - - /// NewFile 文本常量 - - private String newFile; - /// EncodingDetector 文本常量 - /** - * 未知 - */ - private String unknown; - - /// JNotepadStatusBox - - private String row; - - private String column; - - private String wordCount; - - private String encode; public static LocalizationConfig getLocalizationConfig() { return LOCALIZATION_CONFIG; } - public void setLanguagePackName(String languagePackName) { - this.languagePackName = languagePackName; - } - - public String getTitle() { - return title; - } - - public String getSava() { - return sava; - } - - public String getFile() { - return file; - } - - public String getNewly() { - return newly; - } - - public String getOpen() { - return open; - } - - public String getSavaAs() { - return savaAs; - } - - public String getSet() { - return set; - } - - public String getWordWrap() { - return wordWrap; - } - - public String getPlugin() { - return plugin; - } - - public String getAddPlugin() { - return addPlugin; - } - - public String getStatistics() { - return statistics; - } - - public String getOpenConfigurationFile() { - return openConfigurationFile; - } - - public String getTop() { - return top; - } - - public String getLanguage() { - return language; - } - - public String getChinese() { - return chinese; - } - - public String getEnglish() { - return english; - } - - public String getNewFile() { - return newFile; - } - - public String getUnknown() { - return unknown; - } - - public String getRow() { - return row; - } - - public String getColumn() { - return column; - } - - public String getWordCount() { - return wordCount; - } - - public String getEncode() { - return encode; - } - - public String getLanguagePackName() { - return languagePackName; - } public String getTextWrap() { return textWrap; @@ -317,4 +76,12 @@ public class LocalizationConfig { this.textWrap = textWrap; properties.setProperty(TEXT_WRAP, textWrap); } + + private void setLanguage(String language) { + this.language = language; + } + + public String getLanguage() { + return this.language; + } } diff --git a/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java b/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java new file mode 100644 index 0000000..dc17d43 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java @@ -0,0 +1,79 @@ +package org.jcnc.jnotepad.app.i18n; + +import javafx.beans.binding.StringBinding; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.beans.value.ChangeListener; +import org.jcnc.jnotepad.app.config.LocalizationConfig; + +import java.util.Locale; +import java.util.ResourceBundle; + +public class UIResourceBundle { + + private static final UIResourceBundle INSTANCE = new UIResourceBundle(); + private static final String BASENAME = "i18n/i18n"; + + private Locale currentLocale; + + public static final UIResourceBundle getInstance() { + return INSTANCE; + } + + private UIResourceBundle() { + this.resetLocal(); + } + + private ObjectProperty resources = new SimpleObjectProperty<>(); + + public ObjectProperty resourcesProperty() { + return resources; + } + + public final ResourceBundle getResources() { + return resourcesProperty().get(); + } + + public final void setResources(ResourceBundle resources) { + resourcesProperty().set(resources); + } + + public final void resetLocal() { + if (this.currentLocale == LocalizationConfig.getCurrentLocal()) { + return; + } + this.currentLocale = LocalizationConfig.getCurrentLocal(); + ResourceBundle resourceBundle = ResourceBundle.getBundle(BASENAME, currentLocale); + this.setResources(resourceBundle); + + } + + public StringBinding getStringBinding(String key) { + return new StringBinding() { + { + bind(resourcesProperty()); + } + + @Override + public String computeValue() { + return getResources().getString(key); + } + }; + } + + public static void bindStringProperty(StringProperty stringProperty, String key) { + if (stringProperty == null) { + return; + } + stringProperty.bind(getInstance().getStringBinding(key)); + } + + public static String getContent(String key) { + return getInstance().getResources().getString(key); + } + + public void addListener(ChangeListener listener) { + this.resources.addListener(listener); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/app/init/LoadJnotepadConfig.java b/src/main/java/org/jcnc/jnotepad/app/init/LoadJnotepadConfig.java index ee5b91e..858fbf7 100644 --- a/src/main/java/org/jcnc/jnotepad/app/init/LoadJnotepadConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/init/LoadJnotepadConfig.java @@ -85,7 +85,6 @@ public abstract class LoadJnotepadConfig { } catch (IOException e) { PopUpUtil.errorAlert("错误", "读写错误", "配置文件读写错误!"); } - LocalizationConfig.getLocalizationConfig().initLocalizationConfig(); } diff --git a/src/main/java/org/jcnc/jnotepad/app/init/LoadLanguageConfig.java b/src/main/java/org/jcnc/jnotepad/app/init/LoadLanguageConfig.java index ab0808d..747faf5 100644 --- a/src/main/java/org/jcnc/jnotepad/app/init/LoadLanguageConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/init/LoadLanguageConfig.java @@ -8,8 +8,6 @@ import org.slf4j.Logger; import java.io.InputStream; -import static org.jcnc.jnotepad.constants.TextConstants.LANGUAGE_FILE_MAP; - /** * 加载语言配置文件 * @@ -31,12 +29,10 @@ public class LoadLanguageConfig extends LoadJnotepadConfig { String language = parseConfig(inputStream); if (!"".equals(language) && language != null) { log.info("正在加载语言包:{}", language); - localizationConfig.setLanguagePackName(LANGUAGE_FILE_MAP.get(language)); // 刷新语言包 - localizationConfig.initLocalizationConfig(); + localizationConfig.setCurrentLocal(language); JNotepadMenuBar jNotepadMenuBar = JNotepadMenuBar.getMenuBar(); // 刷新菜单栏 - jNotepadMenuBar.initMenuBar(); jNotepadMenuBar.toggleLanguageCheck(language); JNotepadStatusBox.getInstance().initStatusBox(); } diff --git a/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java b/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java index 4242d75..c23864c 100644 --- a/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java +++ b/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java @@ -66,13 +66,7 @@ public class TextConstants { public static final String CHINESE = "chinese"; public static final String LOWER_LANGUAGE = "language"; - /** - * 语言映射 - */ - public static final Map LANGUAGE_FILE_MAP = Map.of( - CHINESE, CH_LANGUAGE_PACK_NAME, - ENGLISH, EN_LANGUAGE_PACK_NAME - ); + /// 配置文件文本常量 /** * 内置配置文件 diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java index 5e56cca..c6bbcfa 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java @@ -3,6 +3,8 @@ package org.jcnc.jnotepad.controller.event.handler; import javafx.event.ActionEvent; import javafx.event.EventHandler; import org.jcnc.jnotepad.app.config.LocalizationConfig; +import org.jcnc.jnotepad.app.i18n.UIResourceBundle; +import org.jcnc.jnotepad.constants.TextConstants; import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.status.JNotepadStatusBox; import org.jcnc.jnotepad.ui.tab.JNotepadTab; @@ -20,7 +22,6 @@ import org.jcnc.jnotepad.view.manager.ViewManager; public class NewFile implements EventHandler { /** - * * 处理新建文件事件。 * * @param event 事件对象 @@ -34,7 +35,7 @@ public class NewFile implements EventHandler { // TODO: refactor:统一TextArea新建、绑定监听器入口 ViewManager viewManager = ViewManager.getInstance(); // 将Tab页添加到TabPane中 - JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(LocalizationConfig.getLocalizationConfig().getNewFile() + JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(UIResourceBundle.getContent(TextConstants.NEW_FILE) + viewManager.selfIncreaseAndGetTabIndex(), textArea)); diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java index bd76b8f..e04b49c 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java @@ -4,6 +4,8 @@ import javafx.application.Platform; import javafx.concurrent.Task; import org.jcnc.jnotepad.Interface.ControllerInterface; import org.jcnc.jnotepad.app.config.LocalizationConfig; +import org.jcnc.jnotepad.app.i18n.UIResourceBundle; +import org.jcnc.jnotepad.constants.TextConstants; import org.jcnc.jnotepad.manager.ThreadPoolManager; import org.jcnc.jnotepad.tool.EncodingDetector; import org.jcnc.jnotepad.tool.LogUtil; @@ -114,7 +116,7 @@ public class Controller implements ControllerInterface { @Override public void updateUiWithNewTextArea(LineNumberTextArea textArea) { ViewManager viewManager = ViewManager.getInstance(); - String tabTitle = LocalizationConfig.getLocalizationConfig().getNewFile() + viewManager.selfIncreaseAndGetTabIndex(); + String tabTitle = UIResourceBundle.getContent(TextConstants.NEW_FILE) + viewManager.selfIncreaseAndGetTabIndex(); JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(tabTitle, textArea)); } diff --git a/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java b/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java index ef70411..628123b 100644 --- a/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java +++ b/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java @@ -41,11 +41,11 @@ public class EncodingDetector { charsetDetector.setText(inputStream); CharsetMatch[] matchList = charsetDetector.detectAll(); if (matchList == null || matchList.length == 0) { - return localizationConfig.getUnknown(); + return null; } CharsetMatch maxConfidence = matchList[0]; if (maxConfidence.getConfidence() < THRESHOLD_CONFIDENCE) { - return localizationConfig.getUnknown(); + return null; } for (int i = 1; i < matchList.length; i++) { CharsetMatch match = matchList[i]; @@ -59,7 +59,7 @@ public class EncodingDetector { } catch (Exception e) { LOG.error("", e); } - return localizationConfig.getUnknown(); + return null; } /** diff --git a/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java b/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java index 6ec15c9..356d282 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java +++ b/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java @@ -8,6 +8,8 @@ import javafx.stage.Stage; import org.jcnc.jnotepad.LunchApp; import org.jcnc.jnotepad.app.config.GlobalConfig; import org.jcnc.jnotepad.app.config.LocalizationConfig; +import org.jcnc.jnotepad.app.i18n.UIResourceBundle; +import org.jcnc.jnotepad.constants.TextConstants; import org.jcnc.jnotepad.controller.event.handler.*; import org.jcnc.jnotepad.exception.AppException; import org.jcnc.jnotepad.tool.JsonUtil; @@ -20,6 +22,7 @@ import org.slf4j.Logger; import java.io.*; import java.nio.charset.Charset; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import static com.fasterxml.jackson.core.JsonEncoding.UTF8; @@ -44,7 +47,7 @@ public class JNotepadMenuBar extends MenuBar { Logger logger = LogUtil.getLogger(this.getClass()); private JNotepadMenuBar() { - + initMenuBar(); } /** @@ -148,16 +151,21 @@ public class JNotepadMenuBar extends MenuBar { * 初始化语言菜单 */ private void initLanguageMenu() { - logger.info("初始化语言菜单:{}", localizationConfig.getLanguage()); + logger.info("初始化语言菜单:{}", UIResourceBundle.getContent(LANGUAGE)); // 语言菜单 - languageMenu = new Menu(localizationConfig.getLanguage()); + languageMenu = new Menu(); + UIResourceBundle.bindStringProperty(languageMenu.textProperty(), LANGUAGE); ToggleGroup languageToggleGroup = new ToggleGroup(); - chineseItem = new RadioMenuItem(localizationConfig.getChinese()); + chineseItem = new RadioMenuItem(); + UIResourceBundle.bindStringProperty(chineseItem.textProperty(), UPPER_CHINESE); + chineseItem.setUserData(Locale.CHINESE); itemMap.put("chineseItem", chineseItem); languageToggleGroup.getToggles().add(chineseItem); - englishItem = new RadioMenuItem(localizationConfig.getEnglish()); + englishItem = new RadioMenuItem(); + UIResourceBundle.bindStringProperty(englishItem.textProperty(), UPPER_ENGLISH); + englishItem.setUserData(Locale.ENGLISH); itemMap.put("englishItem", englishItem); languageToggleGroup.getToggles().add(englishItem); @@ -169,20 +177,26 @@ public class JNotepadMenuBar extends MenuBar { * 初始化文件菜单 */ private void initFileMenu() { - logger.info("初始化文件菜单:{}", localizationConfig.getFile()); + logger.info("初始化文件菜单:{}", UIResourceBundle.getContent(FILE)); // 文件菜单 - fileMenu = new Menu(localizationConfig.getFile()); + fileMenu = new Menu(); + UIResourceBundle.bindStringProperty(fileMenu.textProperty(), FILE); + + newItem = new MenuItem(); + UIResourceBundle.bindStringProperty(newItem.textProperty(), NEW); - newItem = new MenuItem(localizationConfig.getNewly()); itemMap.put("newItem", newItem); - openItem = new MenuItem(localizationConfig.getOpen()); + openItem = new MenuItem(); + UIResourceBundle.bindStringProperty(openItem.textProperty(), OPEN); itemMap.put("openItem", openItem); - saveItem = new MenuItem(localizationConfig.getSava()); + saveItem = new MenuItem(); + UIResourceBundle.bindStringProperty(saveItem.textProperty(), SAVE); itemMap.put("saveItem", saveItem); - saveAsItem = new MenuItem(localizationConfig.getSavaAs()); + saveAsItem = new MenuItem(); + UIResourceBundle.bindStringProperty(saveAsItem.textProperty(), SAVE_AS); itemMap.put("saveAsItem", saveAsItem); fileMenu.getItems().addAll(newItem, openItem, saveItem, saveAsItem); @@ -192,18 +206,22 @@ public class JNotepadMenuBar extends MenuBar { * 初始化设置菜单 */ private void initSettingMenu() { - logger.info("初始化设置菜单:{}", localizationConfig.getSet()); + logger.info("初始化设置菜单:{}", UIResourceBundle.getContent(SET)); // 设置菜单 - setMenu = new Menu(localizationConfig.getSet()); + setMenu = new Menu(); + UIResourceBundle.bindStringProperty(setMenu.textProperty(), SET); - lineFeedItem = new CheckMenuItem(localizationConfig.getWordWrap()); + lineFeedItem = new CheckMenuItem(); + UIResourceBundle.bindStringProperty(lineFeedItem.textProperty(), WORD_WRAP); itemMap.put("lineFeedItem", lineFeedItem); lineFeedItem.selectedProperty().set(true); - topItem = new CheckMenuItem(localizationConfig.getTop()); + topItem = new CheckMenuItem(); + UIResourceBundle.bindStringProperty(topItem.textProperty(), TOP); itemMap.put("topItem", topItem); - openConfigItem = new MenuItem(localizationConfig.getOpenConfigurationFile()); + openConfigItem = new MenuItem(); + UIResourceBundle.bindStringProperty(openConfigItem.textProperty(), OPEN_CONFIGURATION_FILE); itemMap.put("openConfigItem", openConfigItem); itemMap.put("languageMenu", languageMenu); @@ -214,13 +232,17 @@ public class JNotepadMenuBar extends MenuBar { * 初始化插件菜单 */ private void initPluginMenu() { - logger.info("初始化插件菜单:{}", localizationConfig.getPlugin()); + logger.info("初始化插件菜单:{}", UIResourceBundle.getContent(PLUGIN)); // 插件菜单 - pluginMenu = new Menu(localizationConfig.getPlugin()); - addItem = new MenuItem(localizationConfig.getAddPlugin()); + pluginMenu = new Menu(); + UIResourceBundle.bindStringProperty(pluginMenu.textProperty(), PLUGIN); + + addItem = new MenuItem(); + UIResourceBundle.bindStringProperty(addItem.textProperty(), ADD_PLUGIN); itemMap.put("addItem", addItem); - countItem = new MenuItem(localizationConfig.getStatistics()); + countItem = new MenuItem(); + UIResourceBundle.bindStringProperty(countItem.textProperty(), STATISTICS); itemMap.put("countItem", countItem); pluginMenu.getItems().addAll(addItem, countItem); @@ -254,8 +276,10 @@ public class JNotepadMenuBar extends MenuBar { englishItem.setOnAction(new LocalizationHandler() { @Override public void handle(ActionEvent actionEvent) { + try { setCurrentLanguage(ENGLISH); + toggleLanguage(actionEvent); } catch (JsonProcessingException e) { throw new AppException(e.getMessage()); @@ -267,7 +291,7 @@ public class JNotepadMenuBar extends MenuBar { public void handle(ActionEvent actionEvent) { try { setCurrentLanguage(CHINESE); - + toggleLanguage(actionEvent); } catch (JsonProcessingException e) { throw new AppException(e.getMessage()); } @@ -275,6 +299,17 @@ public class JNotepadMenuBar extends MenuBar { }); } + private void toggleLanguage(ActionEvent actionEvent) { + if (actionEvent == null) { + return; + } + RadioMenuItem languageItem = (RadioMenuItem) actionEvent.getSource(); + if (languageItem == null) { + return; + } + LocalizationConfig.setCurrentLocal((Locale) languageItem.getUserData()); + } + /** * 设置当前语言
* @@ -283,7 +318,7 @@ public class JNotepadMenuBar extends MenuBar { */ private void setCurrentLanguage(String language) throws JsonProcessingException { // 如果当前已是该语言则不执行该方法 - if (localizationConfig.getLanguagePackName().equals(LANGUAGE_FILE_MAP.get(language))) { + if (localizationConfig.getLanguage().equals(language)) { return; } boolean flag = false; @@ -315,7 +350,7 @@ public class JNotepadMenuBar extends MenuBar { writer.write(JsonUtil.toJsonString(json)); // 刷新文件 writer.flush(); - // 重新加载语言包和快捷键 + // 重新加载快捷键 View.getInstance().initJnotepadConfigs(LunchApp.getLocalizationConfigs()); logger.info("已刷新语言包!"); logger.info("已刷新快捷键!"); diff --git a/src/main/java/org/jcnc/jnotepad/ui/status/JNotepadStatusBox.java b/src/main/java/org/jcnc/jnotepad/ui/status/JNotepadStatusBox.java index 5839324..01c681f 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/status/JNotepadStatusBox.java +++ b/src/main/java/org/jcnc/jnotepad/ui/status/JNotepadStatusBox.java @@ -1,14 +1,19 @@ package org.jcnc.jnotepad.ui.status; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; import javafx.scene.control.Label; import javafx.scene.control.TextArea; import javafx.scene.layout.HBox; import org.jcnc.jnotepad.app.config.LocalizationConfig; +import org.jcnc.jnotepad.app.i18n.UIResourceBundle; +import org.jcnc.jnotepad.constants.TextConstants; import org.jcnc.jnotepad.ui.tab.JNotepadTab; import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import java.nio.charset.Charset; +import java.util.ResourceBundle; /** * 状态栏组件封装。 @@ -20,16 +25,19 @@ import java.nio.charset.Charset; public class JNotepadStatusBox extends HBox { private static final JNotepadStatusBox STATUS_BOX = new JNotepadStatusBox(); - LocalizationConfig localizationConfig = LocalizationConfig.getLocalizationConfig(); /** * 字数统计及光标 */ private Label statusLabel; + private static final String STATUS_LABEL_FORMAT = "%s : %d \t%s: %d \t%s: %d \t"; + /** * 显示文本编码 */ - private Label enCodingLabel; + private Label encodingLabel; + private final String ENCODING_LABEL_FORMAT = "\t%s : %s"; + private JNotepadStatusBox() { initStatusBox(); @@ -43,14 +51,23 @@ public class JNotepadStatusBox extends HBox { public void initStatusBox() { this.getChildren().clear(); // 创建状态栏 - statusLabel = new Label(localizationConfig.getRow() + ":1 \t" + localizationConfig.getColumn() + ":1 \t" + localizationConfig.getWordCount() + ":0 "); + statusLabel = new Label(); + statusLabel.setText(getStatusBarFormattedText(0, 0, 1)); // 创建新的标签以显示编码信息 - enCodingLabel = new Label(); + encodingLabel = new Label(); updateEncodingLabel(); updateWhenTabSelected(); this.getChildren().add(statusLabel); - this.getChildren().add(enCodingLabel); + this.getChildren().add(encodingLabel); this.getProperties().put("borderpane-margin", new Insets(5, 10, 5, 10)); + + UIResourceBundle.getInstance().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, ResourceBundle oldValue, ResourceBundle newValue) { + updateWhenTabSelected(); + } + }); + } public static JNotepadStatusBox getInstance() { @@ -70,7 +87,7 @@ public class JNotepadStatusBox extends HBox { if (encoding == null) { encoding = Charset.defaultCharset().name(); } - this.enCodingLabel.setText("\t" + localizationConfig.getEncode() + ": " + encoding); + this.encodingLabel.setText(getEncodingFormattedText(encoding)); } /** @@ -86,7 +103,7 @@ public class JNotepadStatusBox extends HBox { int row = getRow(caretPosition, textArea.getText()); int column = getColumn(caretPosition, textArea.getText()); int length = textArea.getLength(); - this.statusLabel.setText(localizationConfig.getRow() + ": " + row + " \t" + localizationConfig.getColumn() + ": " + column + " \t" + localizationConfig.getWordCount() + ": " + length); + this.statusLabel.setText(getStatusBarFormattedText(row, column, length)); } /** @@ -135,4 +152,21 @@ public class JNotepadStatusBox extends HBox { return caretPosition - text.lastIndexOf("\n", caretPosition - 1); } + protected String getStatusBarFormattedText(int row, int column, int wordCount) { + String rowText = UIResourceBundle.getContent(TextConstants.ROW); + String columnText = UIResourceBundle.getContent(TextConstants.COLUMN); + String wordCountText = UIResourceBundle.getContent(TextConstants.WORD_COUNT); + return String.format(STATUS_LABEL_FORMAT, + rowText, + row, + columnText, + column, + wordCountText, + wordCount + ); + } + + protected String getEncodingFormattedText(String encoding) { + return String.format(ENCODING_LABEL_FORMAT, UIResourceBundle.getContent(TextConstants.ENCODE), encoding); + } } diff --git a/src/main/resources/i18n/i18n.properties b/src/main/resources/i18n/i18n.properties new file mode 100644 index 0000000..3c690ee --- /dev/null +++ b/src/main/resources/i18n/i18n.properties @@ -0,0 +1,21 @@ +LANGUAGE=语言 +NEW_FILE=新建文件 +NEW=新建 +SET=设置 +ENGLISH=英文 +STATISTICS=统计字数 +COLUMN=列数 +PLUGIN=插件 +CHINESE=中文 +title=JNotepad +OPEN=打开 +OPEN_CONFIGURATION_FILE=打开配置文件 +TOP=窗口置顶 +WORD_WRAP=自动换行 +WORD_COUNT=字数 +SAVE_AS=另存为 +SAVE=保存 +ROW=行数 +FILE=文件 +ADD_PLUGIN=增加插件 +ENCODE=编码 diff --git a/src/main/resources/i18n/i18n_en.properties b/src/main/resources/i18n/i18n_en.properties new file mode 100644 index 0000000..a15edd1 --- /dev/null +++ b/src/main/resources/i18n/i18n_en.properties @@ -0,0 +1,21 @@ +LANGUAGE=Language +NEW=New +NEW_FILE=New File +SET=Settings +ENGLISH=English +STATISTICS=Word Count +COLUMN=Column +PLUGIN=Plugins +CHINESE=Chinese +title=JNotepad +OPEN=Open +OPEN_CONFIGURATION_FILE=Open Configuration File +TOP=Window Top +WORD_WRAP=Word Wrap +WORD_COUNT=Word Count +SAVE_AS=Save As +SAVE=Save +ROW=Row +FILE=File +ADD_PLUGIN=Add Plugin +ENCODE=Encoding \ No newline at end of file diff --git a/src/main/resources/i18n/i18n_zh_CN.properties b/src/main/resources/i18n/i18n_zh_CN.properties new file mode 100644 index 0000000..3c690ee --- /dev/null +++ b/src/main/resources/i18n/i18n_zh_CN.properties @@ -0,0 +1,21 @@ +LANGUAGE=语言 +NEW_FILE=新建文件 +NEW=新建 +SET=设置 +ENGLISH=英文 +STATISTICS=统计字数 +COLUMN=列数 +PLUGIN=插件 +CHINESE=中文 +title=JNotepad +OPEN=打开 +OPEN_CONFIGURATION_FILE=打开配置文件 +TOP=窗口置顶 +WORD_WRAP=自动换行 +WORD_COUNT=字数 +SAVE_AS=另存为 +SAVE=保存 +ROW=行数 +FILE=文件 +ADD_PLUGIN=增加插件 +ENCODE=编码 -- Gitee From 6679d6e04d2631770c14a2fb1efbacaffbf0079a Mon Sep 17 00:00:00 2001 From: songdragon Date: Sun, 27 Aug 2023 16:54:41 +0800 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E4=B8=8D?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jcnc/jnotepad/constants/TextConstants.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java b/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java index c23864c..57ebb60 100644 --- a/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java +++ b/src/main/java/org/jcnc/jnotepad/constants/TextConstants.java @@ -10,14 +10,8 @@ import org.jcnc.jnotepad.json.DataGenerator; import org.jcnc.jnotepad.json.MyData; import org.jcnc.jnotepad.tool.JsonUtil; -import java.util.Map; - /** - * 文本常量 - *

- * 任何string请都在此处readPropertiesFromFile,然后在 - * src/main/java/org/jcnc/jnotepad/init/Config.java的getXXXXXLanguagePack - * 注册配置文件,设置多语言语言包 + * 文本常量,被多处使用的常量放到此处。如果只有一个class使用,在class中使用private static final声明。 * * @author gewuyou */ @@ -57,10 +51,6 @@ public class TextConstants { public static final String ENCODE = "ENCODE"; /// Config 文本常量 - - public static final String CH_LANGUAGE_PACK_NAME = "ch_language_pack.txt"; - public static final String EN_LANGUAGE_PACK_NAME = "en_language_pack.txt"; - public static final String ENGLISH = "english"; public static final String CHINESE = "chinese"; -- Gitee From 59c8b8f5ed9a79a0e337fa801b99c3d3e92e845a Mon Sep 17 00:00:00 2001 From: songdragon Date: Sun, 27 Aug 2023 17:00:34 +0800 Subject: [PATCH 3/3] =?UTF-8?q?doc:=20=E5=A2=9E=E5=8A=A0UIResourceBundle?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jnotepad/app/i18n/UIResourceBundle.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java b/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java index dc17d43..6135098 100644 --- a/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java +++ b/src/main/java/org/jcnc/jnotepad/app/i18n/UIResourceBundle.java @@ -10,11 +10,22 @@ import org.jcnc.jnotepad.app.config.LocalizationConfig; import java.util.Locale; import java.util.ResourceBundle; +/** + * UI资源绑定,用于加载语言文件。 + * + * @author songdragon + */ public class UIResourceBundle { private static final UIResourceBundle INSTANCE = new UIResourceBundle(); + /** + * resource目录下的i18n/i18nXXX.properties + */ private static final String BASENAME = "i18n/i18n"; + /** + * 当前语言 + */ private Locale currentLocale; public static final UIResourceBundle getInstance() { @@ -25,8 +36,15 @@ public class UIResourceBundle { this.resetLocal(); } + /** + * 资源文件的观察者绑定。 + */ private ObjectProperty resources = new SimpleObjectProperty<>(); + /** + * 获取当前资源文件 + * @return + */ public ObjectProperty resourcesProperty() { return resources; } @@ -39,6 +57,9 @@ public class UIResourceBundle { resourcesProperty().set(resources); } + /** + * 重置当前local + */ public final void resetLocal() { if (this.currentLocale == LocalizationConfig.getCurrentLocal()) { return; @@ -49,6 +70,11 @@ public class UIResourceBundle { } + /** + * 获取key对应的绑定属性内容 + * @param key key + * @return key对应的内容 + */ public StringBinding getStringBinding(String key) { return new StringBinding() { { @@ -62,6 +88,11 @@ public class UIResourceBundle { }; } + /** + * 工具方法:绑定StringProperty和Key对应的内容 + * @param stringProperty + * @param key + */ public static void bindStringProperty(StringProperty stringProperty, String key) { if (stringProperty == null) { return; @@ -69,10 +100,19 @@ public class UIResourceBundle { stringProperty.bind(getInstance().getStringBinding(key)); } + /** + * 获取当前资源中的key值 + * @param key + * @return + */ public static String getContent(String key) { return getInstance().getResources().getString(key); } + /** + * 注册资源变更监听器 + * @param listener + */ public void addListener(ChangeListener listener) { this.resources.addListener(listener); } -- Gitee