diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java index 6ef1ff67d5..18524b3306 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/DownloadSettingsPage.java @@ -27,14 +27,20 @@ import javafx.scene.control.ToggleGroup; import javafx.scene.layout.*; import org.jackhuang.hmcl.setting.DownloadProviders; +import org.jackhuang.hmcl.setting.EnumCommonDirectory; +import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.FetchTask; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.WeakListenerHolder; import org.jackhuang.hmcl.ui.construct.*; import org.jackhuang.hmcl.util.i18n.I18n; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import java.net.Proxy; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; @@ -98,9 +104,37 @@ public DownloadSettingsPage() { } { + var downloadList = new ComponentList(); + VBox downloadThreads = new VBox(16); - downloadThreads.getStyleClass().add("card-non-transparent"); + + ComponentSublist fileCommonLocationSublist = new ComponentSublist(); + { + { + MultiFileItem fileCommonLocation = new MultiFileItem<>(); + fileCommonLocation.loadChildren(Arrays.asList( + new MultiFileItem.Option<>(i18n("launcher.cache_directory.default"), EnumCommonDirectory.DEFAULT), + new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumCommonDirectory.CUSTOM) + .setChooserTitle(i18n("launcher.cache_directory.choose")) + .setSelectionMode(FileSelector.SelectionMode.DIRECTORY) + .bindBidirectional(config().commonDirectoryProperty()) + )); + fileCommonLocation.selectedDataProperty().bindBidirectional(config().commonDirTypeProperty()); + + fileCommonLocationSublist.getContent().add(fileCommonLocation); + fileCommonLocationSublist.setTitle(i18n("launcher.cache_directory")); + fileCommonLocationSublist.setHasSubtitle(true); + fileCommonLocationSublist.subtitleProperty().bind( + Bindings.createObjectBinding(() -> Optional.ofNullable(Settings.instance().getCommonDirectory()) + .orElse(i18n("launcher.cache_directory.disabled")), + config().commonDirectoryProperty(), config().commonDirTypeProperty())); + + JFXButton cleanButton = FXUtils.newBorderButton(i18n("launcher.cache_directory.clean")); + cleanButton.setOnAction(e -> clearCacheDirectory()); + fileCommonLocationSublist.setHeaderRight(cleanButton); + } + { JFXCheckBox chkAutoDownloadThreads = new JFXCheckBox(i18n("settings.launcher.download.threads.auto")); VBox.setMargin(chkAutoDownloadThreads, new Insets(8, 0, 0, 0)); @@ -153,7 +187,8 @@ public DownloadSettingsPage() { } } - content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("download")), downloadThreads); + downloadList.getContent().addAll(fileCommonLocationSublist, downloadThreads); + content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("download")), downloadList); } { @@ -330,4 +365,11 @@ public DownloadSettingsPage() { } } + + private void clearCacheDirectory() { + String commonDirectory = Settings.instance().getCommonDirectory(); + if (commonDirectory != null) { + FileUtils.cleanDirectoryQuietly(Path.of(commonDirectory, "cache")); + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index fab04efdc1..0b73a4ec40 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -20,21 +20,17 @@ import com.jfoenix.controls.JFXButton; import javafx.beans.InvalidationListener; import javafx.beans.WeakInvalidationListener; -import javafx.beans.binding.Bindings; import javafx.beans.property.ObjectProperty; import javafx.beans.property.StringProperty; import javafx.css.PseudoClass; import javafx.geometry.Insets; import javafx.geometry.Pos; -import javafx.geometry.VPos; -import javafx.scene.Cursor; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; -import javafx.scene.layout.*; -import javafx.scene.text.TextAlignment; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; import org.jackhuang.hmcl.Metadata; -import org.jackhuang.hmcl.setting.EnumCommonDirectory; -import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; @@ -61,7 +57,9 @@ import java.nio.file.Path; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; @@ -78,241 +76,193 @@ public final class SettingsPage extends ScrollPane { public SettingsPage() { this.setFitToWidth(true); - VBox rootPane = new VBox(); + VBox rootPane = new VBox(10); rootPane.setPadding(new Insets(10)); this.setContent(rootPane); FXUtils.smoothScrolling(this); - ComponentList settingsPane = new ComponentList(); { + ComponentList updatePaneList = new ComponentList(); { - StackPane sponsorPane = new StackPane(); - sponsorPane.setCursor(Cursor.HAND); - FXUtils.onClicked(sponsorPane, this::onSponsor); - sponsorPane.setPadding(new Insets(8, 0, 8, 0)); - - GridPane gridPane = new GridPane(); - - ColumnConstraints col = new ColumnConstraints(); - col.setHgrow(Priority.SOMETIMES); - col.setMaxWidth(Double.POSITIVE_INFINITY); - - gridPane.getColumnConstraints().setAll(col); + ObjectProperty updateChannel; + { - RowConstraints row = new RowConstraints(); - row.setMinHeight(Double.NEGATIVE_INFINITY); - row.setValignment(VPos.TOP); - row.setVgrow(Priority.SOMETIMES); - gridPane.getRowConstraints().setAll(row); + JFXButton updateButton = FXUtils.newToggleButton4(SVG.UPDATE, 20); + updateButton.setOnAction(e -> onUpdate()); + updateButton.setPadding(Insets.EMPTY); + FXUtils.installFastTooltip(updateButton, i18n("update.tooltip")); - { - Label label = new Label(i18n("sponsor.hmcl")); - label.setWrapText(true); - label.setTextAlignment(TextAlignment.JUSTIFY); - GridPane.setRowIndex(label, 0); - GridPane.setColumnIndex(label, 0); - gridPane.getChildren().add(label); - } + var updatePane = new LineSelectButton() { - sponsorPane.getChildren().setAll(gridPane); - settingsPane.getContent().add(sponsorPane); - } + { + getStyleClass().add("update-pane"); + setNode(IDX_TRAILING, updateButton); + } - ObjectProperty updateChannel; - { + @Override + protected int getTrailingTextIndex() { + return LineComponent.IDX_TRAILING + 1; + } + }; + updateChannel = updatePane.valueProperty(); + updatePane.setTitle(i18n("update")); + updatePane.setValue(UpdateChannel.getChannel()); - JFXButton updateButton = FXUtils.newToggleButton4(SVG.UPDATE, 20); - updateButton.setOnAction(e -> onUpdate()); - updateButton.setPadding(Insets.EMPTY); - FXUtils.installFastTooltip(updateButton, i18n("update.tooltip")); + updatePane.setConverter(channel -> i18n("update.channel." + channel.channelName)); + updatePane.setItems(List.of(UpdateChannel.STABLE, UpdateChannel.DEVELOPMENT)); + updatePane.setDescriptionConverter(channel -> i18n("update.note." + channel.channelName)); - var updatePane = new LineSelectButton() { + final StringProperty lblUpdateSubProperty = updatePane.subtitleProperty(); { - getStyleClass().add("update-pane"); - setNode(IDX_TRAILING, updateButton); - } - - @Override - protected int getTrailingTextIndex() { - return LineComponent.IDX_TRAILING + 1; + updateListener = any -> { + boolean outdated = UpdateChecker.isOutdated(); + + updateButton.setVisible(outdated); + updateButton.setManaged(outdated); + updatePane.pseudoClassStateChanged(PseudoClass.getPseudoClass("active"), outdated); + + if (UpdateChecker.isOutdated()) { + lblUpdateSubProperty.set(i18n("update.newest_version", UpdateChecker.getLatestVersion().getVersion())); + } else if (UpdateChecker.isCheckingUpdate()) { + lblUpdateSubProperty.set(i18n("update.checking")); + } else { + lblUpdateSubProperty.set(i18n("update.latest")); + } + }; + UpdateChecker.latestVersionProperty().addListener(new WeakInvalidationListener(updateListener)); + UpdateChecker.outdatedProperty().addListener(new WeakInvalidationListener(updateListener)); + UpdateChecker.checkingUpdateProperty().addListener(new WeakInvalidationListener(updateListener)); + updateListener.invalidated(null); } - }; - updateChannel = updatePane.valueProperty(); - updatePane.setTitle(i18n("update")); - updatePane.setValue(UpdateChannel.getChannel()); - - updatePane.setConverter(channel -> i18n("update.channel." + channel.channelName)); - updatePane.setItems(List.of(UpdateChannel.STABLE, UpdateChannel.DEVELOPMENT)); - updatePane.setDescriptionConverter(channel -> i18n("update.note." + channel.channelName)); - final StringProperty lblUpdateSubProperty = updatePane.subtitleProperty(); + updatePaneList.getContent().add(updatePane); + } { - updateListener = any -> { - boolean outdated = UpdateChecker.isOutdated(); - - updateButton.setVisible(outdated); - updateButton.setManaged(outdated); - updatePane.pseudoClassStateChanged(PseudoClass.getPseudoClass("active"), outdated); - - if (UpdateChecker.isOutdated()) { - lblUpdateSubProperty.set(i18n("update.newest_version", UpdateChecker.getLatestVersion().getVersion())); - } else if (UpdateChecker.isCheckingUpdate()) { - lblUpdateSubProperty.set(i18n("update.checking")); - } else { - lblUpdateSubProperty.set(i18n("update.latest")); - } + LineToggleButton previewPane = new LineToggleButton(); + previewPane.setTitle(i18n("update.preview")); + previewPane.setSubtitle(i18n("update.preview.subtitle")); + previewPane.selectedProperty().bindBidirectional(config().acceptPreviewUpdateProperty()); + + InvalidationListener checkUpdateListener = e -> { + UpdateChecker.requestCheckUpdate(updateChannel.get(), previewPane.isSelected()); }; - UpdateChecker.latestVersionProperty().addListener(new WeakInvalidationListener(updateListener)); - UpdateChecker.outdatedProperty().addListener(new WeakInvalidationListener(updateListener)); - UpdateChecker.checkingUpdateProperty().addListener(new WeakInvalidationListener(updateListener)); - updateListener.invalidated(null); + updateChannel.addListener(checkUpdateListener); + previewPane.selectedProperty().addListener(checkUpdateListener); + + updatePaneList.getContent().add(previewPane); } - settingsPane.getContent().add(updatePane); - } + { + LineToggleButton disableAutoShowUpdateDialogPane = new LineToggleButton(); + disableAutoShowUpdateDialogPane.setTitle(i18n("update.disable_auto_show_update_dialog")); + disableAutoShowUpdateDialogPane.setSubtitle(i18n("update.disable_auto_show_update_dialog.subtitle")); + disableAutoShowUpdateDialogPane.selectedProperty().bindBidirectional(config().disableAutoShowUpdateDialogProperty()); + updatePaneList.getContent().add(disableAutoShowUpdateDialogPane); + } - { - LineToggleButton previewPane = new LineToggleButton(); - previewPane.setTitle(i18n("update.preview")); - previewPane.setSubtitle(i18n("update.preview.subtitle")); - previewPane.selectedProperty().bindBidirectional(config().acceptPreviewUpdateProperty()); - - InvalidationListener checkUpdateListener = e -> { - UpdateChecker.requestCheckUpdate(updateChannel.get(), previewPane.isSelected()); - }; - updateChannel.addListener(checkUpdateListener); - previewPane.selectedProperty().addListener(checkUpdateListener); - - settingsPane.getContent().add(previewPane); + rootPane.getChildren().addAll(ComponentList.createComponentListTitle(i18n("update")), updatePaneList); } { - LineToggleButton disableAutoShowUpdateDialogPane = new LineToggleButton(); - disableAutoShowUpdateDialogPane.setTitle(i18n("update.disable_auto_show_update_dialog")); - disableAutoShowUpdateDialogPane.setSubtitle(i18n("update.disable_auto_show_update_dialog.subtitle")); - disableAutoShowUpdateDialogPane.selectedProperty().bindBidirectional(config().disableAutoShowUpdateDialogProperty()); - settingsPane.getContent().add(disableAutoShowUpdateDialogPane); - } + ComponentList languagePaneList = new ComponentList(); - if (AprilFools.isShowAprilFoolsSettings()) { - LineToggleButton disableAprilFools = new LineToggleButton(); - disableAprilFools.setTitle(i18n("settings.launcher.disable_april_fools")); - disableAprilFools.setSubtitle(i18n("settings.take_effect_after_restart")); - disableAprilFools.selectedProperty().bindBidirectional(config().disableAprilFoolsProperty()); - settingsPane.getContent().add(disableAprilFools); - } - - { - MultiFileItem fileCommonLocation = new MultiFileItem<>(); - fileCommonLocation.loadChildren(Arrays.asList( - new MultiFileItem.Option<>(i18n("launcher.cache_directory.default"), EnumCommonDirectory.DEFAULT), - new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumCommonDirectory.CUSTOM) - .setChooserTitle(i18n("launcher.cache_directory.choose")) - .setSelectionMode(FileSelector.SelectionMode.DIRECTORY) - .bindBidirectional(config().commonDirectoryProperty()) - )); - fileCommonLocation.selectedDataProperty().bindBidirectional(config().commonDirTypeProperty()); - - ComponentSublist fileCommonLocationSublist = new ComponentSublist(); - fileCommonLocationSublist.getContent().add(fileCommonLocation); - fileCommonLocationSublist.setTitle(i18n("launcher.cache_directory")); - fileCommonLocationSublist.setHasSubtitle(true); - fileCommonLocationSublist.subtitleProperty().bind( - Bindings.createObjectBinding(() -> Optional.ofNullable(Settings.instance().getCommonDirectory()) - .orElse(i18n("launcher.cache_directory.disabled")), - config().commonDirectoryProperty(), config().commonDirTypeProperty())); - - JFXButton cleanButton = FXUtils.newBorderButton(i18n("launcher.cache_directory.clean")); - cleanButton.setOnAction(e -> clearCacheDirectory()); - fileCommonLocationSublist.setHeaderRight(cleanButton); - - settingsPane.getContent().add(fileCommonLocationSublist); - } + { + var chooseLanguagePane = new LineSelectButton(); + chooseLanguagePane.setTitle(i18n("settings.launcher.language")); + chooseLanguagePane.setSubtitle(i18n("settings.take_effect_after_restart")); + + SupportedLocale currentLocale = I18n.getLocale(); + chooseLanguagePane.setConverter(locale -> { + if (locale.isDefault()) + return locale.getDisplayName(currentLocale); + else if (locale.isSameLanguage(currentLocale)) + return locale.getDisplayName(locale); + else + return locale.getDisplayName(currentLocale) + " - " + locale.getDisplayName(locale); + }); + chooseLanguagePane.setItems(SupportedLocale.getSupportedLocales()); + chooseLanguagePane.valueProperty().bindBidirectional(config().localizationProperty()); + + languagePaneList.getContent().add(chooseLanguagePane); + + LineToggleButton disableAutoGameOptionsPane = new LineToggleButton(); + disableAutoGameOptionsPane.setTitle(i18n("settings.launcher.disable_auto_game_options")); + disableAutoGameOptionsPane.selectedProperty().bindBidirectional(config().disableAutoGameOptionsProperty()); + + languagePaneList.getContent().add(disableAutoGameOptionsPane); + } - { - var chooseLanguagePane = new LineSelectButton(); - chooseLanguagePane.setTitle(i18n("settings.launcher.language")); - chooseLanguagePane.setSubtitle(i18n("settings.take_effect_after_restart")); - - SupportedLocale currentLocale = I18n.getLocale(); - chooseLanguagePane.setConverter(locale -> { - if (locale.isDefault()) - return locale.getDisplayName(currentLocale); - else if (locale.isSameLanguage(currentLocale)) - return locale.getDisplayName(locale); - else - return locale.getDisplayName(currentLocale) + " - " + locale.getDisplayName(locale); - }); - chooseLanguagePane.setItems(SupportedLocale.getSupportedLocales()); - chooseLanguagePane.valueProperty().bindBidirectional(config().localizationProperty()); - - settingsPane.getContent().add(chooseLanguagePane); + rootPane.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.language")), languagePaneList); } { - LineToggleButton disableAutoGameOptionsPane = new LineToggleButton(); - disableAutoGameOptionsPane.setTitle(i18n("settings.launcher.disable_auto_game_options")); - disableAutoGameOptionsPane.selectedProperty().bindBidirectional(config().disableAutoGameOptionsProperty()); + ComponentList miscPaneList = new ComponentList(); + + if (AprilFools.isShowAprilFoolsSettings()) { + LineToggleButton disableAprilFools = new LineToggleButton(); + disableAprilFools.setTitle(i18n("settings.launcher.disable_april_fools")); + disableAprilFools.setSubtitle(i18n("settings.take_effect_after_restart")); + disableAprilFools.selectedProperty().bindBidirectional(config().disableAprilFoolsProperty()); + miscPaneList.getContent().add(disableAprilFools); + } - settingsPane.getContent().add(disableAutoGameOptionsPane); - } + { + LineToggleButton allowAutoAgentPane = new LineToggleButton(); + allowAutoAgentPane.setTitle(i18n("settings.launcher.allow_auto_agent")); + allowAutoAgentPane.setSubtitle(i18n("settings.launcher.allow_auto_agent.subtitle")); + allowAutoAgentPane.selectedProperty().bindBidirectional(config().allowAutoAgentProperty()); - { - LineToggleButton allowAutoAgentPane = new LineToggleButton(); - allowAutoAgentPane.setTitle(i18n("settings.launcher.allow_auto_agent")); - allowAutoAgentPane.setSubtitle(i18n("settings.launcher.allow_auto_agent.subtitle")); - allowAutoAgentPane.selectedProperty().bindBidirectional(config().allowAutoAgentProperty()); + miscPaneList.getContent().add(allowAutoAgentPane); + } - settingsPane.getContent().add(allowAutoAgentPane); - } + { + BorderPane debugPane = new BorderPane(); + + Label left = new Label(i18n("settings.launcher.debug")); + BorderPane.setAlignment(left, Pos.CENTER_LEFT); + debugPane.setLeft(left); + + JFXButton openLogFolderButton = new JFXButton(i18n("settings.launcher.launcher_log.reveal")); + openLogFolderButton.setOnAction(e -> openLogFolder()); + openLogFolderButton.getStyleClass().add("jfx-button-border"); + if (LOG.getLogFile() == null) + openLogFolderButton.setDisable(true); + + SpinnerPane exportLogPane = new SpinnerPane(); + + JFXButton logButton = FXUtils.newBorderButton(i18n("settings.launcher.launcher_log.export")); + exportLogPane.setContent(logButton); + logButton.setOnAction(e -> { + exportLogPane.showSpinner(); + onExportLogs().whenCompleteAsync((result, exception) -> { + exportLogPane.hideSpinner(); + if (exception == null) { + Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", result)); + FXUtils.showFileInExplorer(result); + } else { + LOG.warning("Failed to export logs", exception); + Controllers.dialog( + i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), + null, + MessageType.ERROR + ); + } + }, Schedulers.javafx()); + }); - { - BorderPane debugPane = new BorderPane(); - - Label left = new Label(i18n("settings.launcher.debug")); - BorderPane.setAlignment(left, Pos.CENTER_LEFT); - debugPane.setLeft(left); - - JFXButton openLogFolderButton = new JFXButton(i18n("settings.launcher.launcher_log.reveal")); - openLogFolderButton.setOnAction(e -> openLogFolder()); - openLogFolderButton.getStyleClass().add("jfx-button-border"); - if (LOG.getLogFile() == null) - openLogFolderButton.setDisable(true); - - SpinnerPane exportLogPane = new SpinnerPane(); - - JFXButton logButton = FXUtils.newBorderButton(i18n("settings.launcher.launcher_log.export")); - exportLogPane.setContent(logButton); - logButton.setOnAction(e -> { - exportLogPane.showSpinner(); - onExportLogs().whenCompleteAsync((result, exception) -> { - exportLogPane.hideSpinner(); - if (exception == null) { - Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", result)); - FXUtils.showFileInExplorer(result); - } else { - LOG.warning("Failed to export logs", exception); - Controllers.dialog( - i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), - null, - MessageType.ERROR - ); - } - }, Schedulers.javafx()); - }); + HBox buttonBox = new HBox(); + buttonBox.setSpacing(10); + buttonBox.getChildren().addAll(openLogFolderButton, exportLogPane); + BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); + debugPane.setRight(buttonBox); - HBox buttonBox = new HBox(); - buttonBox.setSpacing(10); - buttonBox.getChildren().addAll(openLogFolderButton, exportLogPane); - BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); - debugPane.setRight(buttonBox); + miscPaneList.getContent().add(debugPane); + } - settingsPane.getContent().add(debugPane); + rootPane.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.misc")), miscPaneList); } - - rootPane.getChildren().add(settingsPane); } } @@ -451,15 +401,4 @@ private CompletableFuture onExportLogs() { return outputFile; }), Schedulers.io()); } - - private void onSponsor() { - FXUtils.openLink("https://github.com/HMCL-dev/HMCL"); - } - - private void clearCacheDirectory() { - String commonDirectory = Settings.instance().getCommonDirectory(); - if (commonDirectory != null) { - FileUtils.cleanDirectoryQuietly(Path.of(commonDirectory, "cache")); - } - } } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index e13e61bd67..533ce5c2cc 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1482,6 +1482,7 @@ settings.launcher.download_source=Download Source settings.launcher.download_source.auto=Automatically Choose Download Sources settings.launcher.default_addon_source=Default Addon Source settings.launcher.enable_game_list=Show instance list in homepage +settings.launcher.misc=Misc settings.launcher.font=Font settings.launcher.font.anti_aliasing=Anti-aliasing settings.launcher.font.anti_aliasing.auto=Auto diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 555f135af8..1fb5f9dada 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1272,6 +1272,7 @@ settings.launcher.download_source=下載來源 settings.launcher.download_source.auto=自動選取下載來源 settings.launcher.default_addon_source=遊戲內容預設下載來源 settings.launcher.enable_game_list=在首頁內顯示遊戲清單 +settings.launcher.misc=雜項 settings.launcher.font=字體 settings.launcher.font.anti_aliasing=反鋸齒 settings.launcher.font.anti_aliasing.auto=自動 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index b251db3d68..f0c116c7df 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1277,6 +1277,7 @@ settings.launcher.download_source=下载源 settings.launcher.download_source.auto=自动选择下载源 settings.launcher.default_addon_source=游戏内容默认下载源 settings.launcher.enable_game_list=在主页内显示版本列表 +settings.launcher.misc=杂项 settings.launcher.font=字体 settings.launcher.font.anti_aliasing=抗锯齿 settings.launcher.font.anti_aliasing.auto=自动