From e903f0ff691e9e0fe330c2ac690ffbbee0d26cdb Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Wed, 4 Feb 2015 17:23:41 -0800 Subject: [PATCH] Added ability for language files to opt-in to loading using normal Java properties format. This allows for escape characters, as well as keeping %d and %f replacements in tact. To opt-in, the lang file must have this comment line: # PARSE_ESCAPES As this is opt-in, any errors resulting from misused format strings is on the modder/end user. --- .../client/resources/Locale.java.patch | 11 ++++ .../minecraft/util/StringTranslate.java.patch | 7 ++- .../fml/common/FMLCommonHandler.java | 51 +++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 fml/patches/minecraft/net/minecraft/client/resources/Locale.java.patch diff --git a/fml/patches/minecraft/net/minecraft/client/resources/Locale.java.patch b/fml/patches/minecraft/net/minecraft/client/resources/Locale.java.patch new file mode 100644 index 000000000..fc84931f7 --- /dev/null +++ b/fml/patches/minecraft/net/minecraft/client/resources/Locale.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/net/minecraft/client/resources/Locale.java ++++ ../src-work/minecraft/net/minecraft/client/resources/Locale.java +@@ -107,6 +107,8 @@ + + private void func_135021_a(InputStream p_135021_1_) throws IOException + { ++ p_135021_1_ = net.minecraftforge.fml.common.FMLCommonHandler.instance().loadLanguage(field_135032_a, p_135021_1_); ++ if (p_135021_1_ == null) return; + Iterator iterator = IOUtils.readLines(p_135021_1_, Charsets.UTF_8).iterator(); + + while (iterator.hasNext()) diff --git a/fml/patches/minecraft/net/minecraft/util/StringTranslate.java.patch b/fml/patches/minecraft/net/minecraft/util/StringTranslate.java.patch index 4c35a2080..cbdfc628a 100644 --- a/fml/patches/minecraft/net/minecraft/util/StringTranslate.java.patch +++ b/fml/patches/minecraft/net/minecraft/util/StringTranslate.java.patch @@ -1,6 +1,6 @@ --- ../src-base/minecraft/net/minecraft/util/StringTranslate.java +++ ../src-work/minecraft/net/minecraft/util/StringTranslate.java -@@ -18,16 +18,35 @@ +@@ -18,16 +18,38 @@ { private static final Pattern field_111053_a = Pattern.compile("%(\\d+\\$)?[\\d\\.]*[df]"); private static final Splitter field_135065_b = Splitter.on('=').limit(2); @@ -35,10 +35,13 @@ try { - InputStream inputstream = StringTranslate.class.getResourceAsStream("/assets/minecraft/lang/en_US.lang"); ++ inputstream = net.minecraftforge.fml.common.FMLCommonHandler.instance().loadLanguage(table, inputstream); ++ if (inputstream == null) return table; ++ Iterator iterator = IOUtils.readLines(inputstream, Charsets.UTF_8).iterator(); while (iterator.hasNext()) -@@ -42,17 +61,17 @@ +@@ -42,17 +64,17 @@ { String s1 = astring[0]; String s2 = field_111053_a.matcher(astring[1]).replaceAll("%$1s"); diff --git a/fml/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java b/fml/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java index 391ecf966..5fdbfe7a9 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java @@ -12,10 +12,18 @@ package net.minecraftforge.fml.common; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; @@ -50,6 +58,8 @@ import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.server.FMLServerHandler; +import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; @@ -685,4 +695,45 @@ public class FMLCommonHandler FMLLog.log(Level.FATAL, e, "Exception caught executing FutureTask: " + e.toString()); } } + + /** + * Loads a lang file, first searching for a marker to enable the 'extended' format {escape charaters} + * If the marker is not found it simply returns and let the vanilla code load things. + * The Marker is 'PARSE_ESCAPES' by itself on a line starting with '#' as such: + * #PARSE_ESCAPES + * + * @param table The Map to load each key/value pair into. + * @param inputstream Input stream containing the lang file. + * @return A new InputStream that vanilla uses to load normal Lang files, Null if this is a 'enhanced' file and loading is done. + */ + public InputStream loadLanguage(Map table, InputStream inputstream) throws IOException + { + byte[] data = IOUtils.toByteArray(new InputStreamReader(inputstream, Charsets.UTF_8)); + + boolean isEnhanced = false; + for (String line : IOUtils.readLines(new ByteArrayInputStream(data), Charsets.UTF_8)) + { + if (line.charAt(0) == '#') + { + line = line.substring(1).trim(); + if (line.equals("PARSE_ESCAPES")) + { + isEnhanced = true; + break; + } + } + } + + if (!isEnhanced) + return new ByteArrayInputStream(data); + + Properties props = new Properties(); + props.load(new InputStreamReader(new ByteArrayInputStream(data), Charsets.UTF_8)); + for (Entry e : props.entrySet()) + { + table.put((String)e.getKey(), (String)e.getValue()); + } + props.clear(); + return null; + } }