diff --git a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
index e79e48a7..a14aa963 100644
--- a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
+++ b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
@@ -16,6 +16,11 @@
package net.fabricmc.mappingio.format;
+import java.util.Locale;
+
+import net.fabricmc.mappingio.i18n.I18n;
+import net.fabricmc.mappingio.i18n.MioLocale;
+
/**
* Represents a supported mapping format. Feature comparison table:
*
@@ -98,48 +103,48 @@ public enum MappingFormat {
/**
* The {@code Tiny} mapping format, as specified here.
*/
- TINY_FILE("Tiny file", "tiny", true, true, false, false, false),
+ TINY_FILE("tiny", true, true, false, false, false),
/**
* The {@code Tiny v2} mapping format, as specified here.
*/
- TINY_2_FILE("Tiny v2 file", "tiny", true, true, true, true, true),
+ TINY_2_FILE("tiny", true, true, true, true, true),
/**
* Enigma's mapping format, as specified here.
*/
- ENIGMA_FILE("Enigma file", "mapping", false, true, true, true, false),
+ ENIGMA_FILE("mapping", false, true, true, true, false),
/**
* Enigma's mapping format (in directory form), as specified here.
*/
- ENIGMA_DIR("Enigma directory", null, false, true, true, true, false),
+ ENIGMA_DIR(null, false, true, true, true, false),
/**
* The {@code SRG} ({@code Searge RetroGuard}) mapping format, as specified here.
*/
- SRG_FILE("SRG file", "srg", false, false, false, false, false),
+ SRG_FILE("srg", false, false, false, false, false),
/**
* The {@code TSRG} ({@code Tiny SRG}, since it saves disk space over SRG) mapping format, as specified here.
*/
- TSRG_FILE("TSRG file", "tsrg", false, false, false, false, false),
+ TSRG_FILE("tsrg", false, false, false, false, false),
/**
* The {@code TSRG v2} mapping format, as specified here.
*/
- TSRG_2_FILE("TSRG2 file", "tsrg", true, true, false, true, false),
+ TSRG_2_FILE("tsrg", true, true, false, true, false),
/**
* ProGuard's mapping format, as specified here.
*/
- PROGUARD_FILE("ProGuard file", "txt", false, true, false, false, false);
+ PROGUARD_FILE("txt", false, true, false, false, false);
- MappingFormat(String name, String fileExt,
- boolean hasNamespaces, boolean hasFieldDescriptors,
+ MappingFormat(String fileExt, boolean hasNamespaces, boolean hasFieldDescriptors,
boolean supportsComments, boolean supportsArgs, boolean supportsLocals) {
- this.name = name;
this.fileExt = fileExt;
+ this.translationKey = "format." + name().toLowerCase(Locale.ROOT);
+ this.name = getName(MioLocale.EN_US);
this.hasNamespaces = hasNamespaces;
this.hasFieldDescriptors = hasFieldDescriptors;
this.supportsComments = supportsComments;
@@ -147,6 +152,10 @@ public enum MappingFormat {
this.supportsLocals = supportsLocals;
}
+ public String getName(MioLocale locale) {
+ return I18n.translate(translationKey, locale);
+ }
+
public boolean hasSingleFile() {
return fileExt != null;
}
@@ -157,6 +166,7 @@ public String getGlobPattern() {
return "*."+fileExt;
}
+ /** @deprecated Use {@link #getName()} instead. */
public final String name;
public final String fileExt;
public final boolean hasNamespaces;
@@ -164,4 +174,5 @@ public String getGlobPattern() {
public final boolean supportsComments;
public final boolean supportsArgs;
public final boolean supportsLocals;
+ private final String translationKey;
}
diff --git a/src/main/java/net/fabricmc/mappingio/i18n/I18n.java b/src/main/java/net/fabricmc/mappingio/i18n/I18n.java
new file mode 100644
index 00000000..41e11095
--- /dev/null
+++ b/src/main/java/net/fabricmc/mappingio/i18n/I18n.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2023 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.mappingio.i18n;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import org.jetbrains.annotations.ApiStatus;
+
+@ApiStatus.Internal
+public class I18n {
+ private I18n() {
+ }
+
+ public static String translate(String key, MioLocale locale, Object... args) {
+ return String.format(translate(key, locale), args);
+ }
+
+ public static String translate(String key, MioLocale locale) {
+ try {
+ return messageBundles.getOrDefault(locale, load(locale)).getString(key);
+ } catch (Exception e) {
+ System.err.println("Exception while translating key " + key + " to locale " + locale.id + ": " + e.getMessage());
+ if (locale == fallbackLocale) return key;
+
+ try {
+ return messageBundles.getOrDefault(fallbackLocale, load(fallbackLocale)).getString(key);
+ } catch (Exception e2) {
+ System.err.println("Exception while translating key " + key + " to fallback locale: " + e2.getMessage());
+ return key;
+ }
+ }
+ }
+
+ private static ResourceBundle load(MioLocale locale) {
+ ResourceBundle resBundle;
+ String resName = String.format("/i18n/%s.properties", locale.id);
+ URL resUrl = I18n.class.getResource(resName);
+
+ if (resUrl == null) {
+ throw new RuntimeException("Locale resource not found: " + resName);
+ }
+
+ try (Reader reader = new InputStreamReader(resUrl.openStream(), StandardCharsets.UTF_8)) {
+ resBundle = new PropertyResourceBundle(reader);
+ messageBundles.put(locale, resBundle);
+ return resBundle;
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to load " + resName, e);
+ }
+ }
+
+ private static final MioLocale fallbackLocale = MioLocale.EN_US;
+ private static final Map messageBundles = new HashMap<>();
+}
diff --git a/src/main/java/net/fabricmc/mappingio/i18n/MioLocale.java b/src/main/java/net/fabricmc/mappingio/i18n/MioLocale.java
new file mode 100644
index 00000000..0a535a9a
--- /dev/null
+++ b/src/main/java/net/fabricmc/mappingio/i18n/MioLocale.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2023 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.mappingio.i18n;
+
+public enum MioLocale {
+ EN_US("en_us");
+
+ MioLocale(String id) {
+ this.id = id;
+ }
+
+ final String id;
+}
diff --git a/src/main/resources/i18n/en_us.properties b/src/main/resources/i18n/en_us.properties
new file mode 100644
index 00000000..244556f0
--- /dev/null
+++ b/src/main/resources/i18n/en_us.properties
@@ -0,0 +1,9 @@
+format.tiny_file = Tiny File
+format.tiny_2_file = Tiny v2 File
+format.enigma_file = Enigma File
+format.enigma_dir = Enigma Directory
+format.mcp_dir = MCP Directory
+format.srg_file = SRG File
+format.tsrg_file = TSRG File
+format.tsrg_2_file = TSRG2 File
+format.proguard_file = ProGuard File
diff --git a/src/test/java/net/fabricmc/mappingio/i18n/I18nTest.java b/src/test/java/net/fabricmc/mappingio/i18n/I18nTest.java
new file mode 100644
index 00000000..e79f9e70
--- /dev/null
+++ b/src/test/java/net/fabricmc/mappingio/i18n/I18nTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.mappingio.i18n;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+import net.fabricmc.mappingio.format.MappingFormat;
+
+public class I18nTest {
+ @Test
+ public void mappingFormats() {
+ for (MappingFormat format : MappingFormat.values()) {
+ String enUsName = format.getName(MioLocale.EN_US);
+ assertTrue(format.name.equals(enUsName));
+
+ for (MioLocale locale : MioLocale.values()) {
+ String translatedName = format.getName(locale);
+ assertFalse(translatedName.startsWith("format."));
+
+ if (locale != MioLocale.EN_US) {
+ assertFalse(translatedName.equals(enUsName));
+ }
+ }
+ }
+ }
+}