From 48d315300ef495b3475f23dc63bc8952bf215c42 Mon Sep 17 00:00:00 2001 From: Oskar Wiksten Date: Thu, 7 Feb 2013 15:35:51 +0000 Subject: [PATCH 1/5] Parse translations from MO files. --- .../conversation/ConversationLoader.java | 9 +- .../AndorsTrail/resource/ResourceLoader.java | 21 ++- .../resource/TranslationLoader.java | 160 ++++++++++++++++++ .../parsers/ActorConditionsTypeParser.java | 11 +- .../parsers/ConversationListParser.java | 19 ++- .../resource/parsers/ItemCategoryParser.java | 12 +- .../resource/parsers/ItemTypeParser.java | 15 +- .../resource/parsers/MonsterTypeParser.java | 15 +- .../resource/parsers/QuestParser.java | 14 +- 9 files changed, 240 insertions(+), 36 deletions(-) create mode 100644 AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java index 97e0aff19..62ecdf671 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java @@ -6,6 +6,7 @@ import java.util.HashMap; import android.content.res.Resources; import com.gpl.rpg.AndorsTrail.resource.ResourceLoader; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.ConversationListParser; public final class ConversationLoader { @@ -19,11 +20,13 @@ public final class ConversationLoader { if (conversationCollection.hasPhrase(phraseID)) { return conversationCollection.getPhrase(phraseID); } - - ConversationListParser conversationListParser = new ConversationListParser(); + + TranslationLoader translationLoader = new TranslationLoader(r.getAssets()); + ConversationListParser conversationListParser = new ConversationListParser(translationLoader); int resourceID = resourceIDsPerPhraseID.get(phraseID); conversationCollection.initialize(conversationListParser, ResourceLoader.readStringFromRaw(r, resourceID)); - + translationLoader.close(); + return conversationCollection.getPhrase(phraseID); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java index f48f6b530..2bb3dfa59 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java @@ -41,7 +41,9 @@ public final class ResourceLoader { taskStart = start; final int mTileSize = world.tileManager.tileSize; - + + TranslationLoader translationLoader = new TranslationLoader(r.getAssets()); + DynamicTileLoader loader = new DynamicTileLoader(world.tileManager.tileCache); prepareTilesets(loader, mTileSize); if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("prepareTilesets"); @@ -75,7 +77,7 @@ public final class ResourceLoader { // ======================================================================== // Load item categories - final ItemCategoryParser itemCategoryParser = new ItemCategoryParser(); + final ItemCategoryParser itemCategoryParser = new ItemCategoryParser(translationLoader); final TypedArray categoriesToLoad = r.obtainTypedArray(itemCategoriesResourceId); for (int i = 0; i < categoriesToLoad.length(); ++i) { world.itemCategories.initialize(itemCategoryParser, readStringFromRaw(r, categoriesToLoad, i)); @@ -85,7 +87,7 @@ public final class ResourceLoader { // ======================================================================== // Load condition types - final ActorConditionsTypeParser actorConditionsTypeParser = new ActorConditionsTypeParser(loader); + final ActorConditionsTypeParser actorConditionsTypeParser = new ActorConditionsTypeParser(loader, translationLoader); final TypedArray conditionsToLoad = r.obtainTypedArray(actorConditionsResourceId); for (int i = 0; i < conditionsToLoad.length(); ++i) { world.actorConditionsTypes.initialize(actorConditionsTypeParser, readStringFromRaw(r, conditionsToLoad, i)); @@ -101,7 +103,7 @@ public final class ResourceLoader { // ======================================================================== // Load items - final ItemTypeParser itemTypeParser = new ItemTypeParser(loader, world.actorConditionsTypes, world.itemCategories); + final ItemTypeParser itemTypeParser = new ItemTypeParser(loader, world.actorConditionsTypes, world.itemCategories, translationLoader); final TypedArray itemsToLoad = r.obtainTypedArray(itemsResourceId); for (int i = 0; i < itemsToLoad.length(); ++i) { world.itemTypes.initialize(itemTypeParser, readStringFromRaw(r, itemsToLoad, i)); @@ -123,7 +125,7 @@ public final class ResourceLoader { // ======================================================================== // Load quests - final QuestParser questParser = new QuestParser(); + final QuestParser questParser = new QuestParser(translationLoader); final TypedArray questsToLoad = r.obtainTypedArray(questsResourceId); for (int i = 0; i < questsToLoad.length(); ++i) { world.quests.initialize(questParser, readStringFromRaw(r, questsToLoad, i)); @@ -134,7 +136,7 @@ public final class ResourceLoader { // ======================================================================== // Load conversations - final ConversationListParser conversationListParser = new ConversationListParser(); + final ConversationListParser conversationListParser = new ConversationListParser(translationLoader); final TypedArray conversationsListsToLoad = r.obtainTypedArray(conversationsListsResourceId); for (int i = 0; i < conversationsListsToLoad.length(); ++i) { ConversationCollection conversations = new ConversationCollection(); @@ -147,7 +149,7 @@ public final class ResourceLoader { // ======================================================================== // Load monsters - final MonsterTypeParser monsterTypeParser = new MonsterTypeParser(world.dropLists, world.actorConditionsTypes, loader); + final MonsterTypeParser monsterTypeParser = new MonsterTypeParser(world.dropLists, world.actorConditionsTypes, loader, translationLoader); final TypedArray monstersToLoad = r.obtainTypedArray(monstersResourceId); for (int i = 0; i < monstersToLoad.length(); ++i) { world.monsterTypes.initialize(monsterTypeParser, readStringFromRaw(r, monstersToLoad, i)); @@ -186,7 +188,8 @@ public final class ResourceLoader { WorldMapParser.read(r, R.xml.worldmap, world.maps); if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("WorldMapParser"); // ======================================================================== - + + translationLoader.close(); if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { @@ -227,7 +230,7 @@ public final class ResourceLoader { final Size src_sz20x12 = new Size(20, 12); final Size src_mapTileSize = new Size(16, 8); final Size src_mapTileSize7 = new Size(16, 7); - + loader.prepareTileset(R.drawable.char_hero, "char_hero", src_sz1x1, defaultTileSize); loader.prepareTileset(R.drawable.ui_selections, "ui_selections", new Size(5, 1), defaultTileSize); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java new file mode 100644 index 000000000..95b3bcdc2 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java @@ -0,0 +1,160 @@ +package com.gpl.rpg.AndorsTrail.resource; + +import android.content.res.AssetManager; +import com.gpl.rpg.AndorsTrail.util.L; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +public final class TranslationLoader { + private final BinaryMoFileParser parser; + + public TranslationLoader(AssetManager mgr) { + BinaryMoFileParser parser = null; + try { + InputStream is = mgr.open("messages.mo"); + parser = new BinaryMoFileParser(is); + } catch (IOException e) { + L.log("ERROR: Reading from translation asset failed: " + e.toString()); + } + this.parser = parser; + } + + private String tr(String s) { + if (s == null) return null; + if (s.length() <= 1) return s; + if (parser == null) return s; + try { + //String t = parser.translate(s); + //L.log(translations.size() + " : " + s + " -> " + t); + //return t; + return parser.translate(s); + } catch (IOException e) { + return s; + } + } + + public void close() { + if (parser == null) return; + try { + parser.close(); + } catch (IOException e) { } + } + + public String translateItemCategoryName(String s) { return tr(s); } + public String translateActorConditionName(String s) { return tr(s); } + public String translateItemTypeName(String s) { return tr(s); } + public String translateMonsterTypeName(String s) { return tr(s); } + public String translateQuestName(String s) { return tr(s); } + public String translateQuestLogEntry(String s) { return tr(s); } + public String translateConversationPhrase(String s) { return tr(s); } + public String translateConversationReply(String s) { return tr(s); } + + //public static HashSet translations = new HashSet(); + + private static final class BinaryMoFileParser { + private final InputStream is; + private final BufferedInputStream reader; + private final int numStrings; + private final int offsetOriginalStrings; + private final int offsetTranslatedStrings; + + public BinaryMoFileParser(InputStream is) throws IOException { + this.is = is; + this.reader = new BufferedInputStream(is); + this.reader.mark(9999999); + int magic = readIntLE(); + if (magic != 0x950412de) throw new IOException("Invalid magic in MO file"); + this.reader.skip(4); + numStrings = readIntLE(); + offsetOriginalStrings = readIntLE(); + offsetTranslatedStrings = readIntLE(); + } + + public void close() throws IOException { + reader.close(); + is.close(); + } + + private final Charset charset = Charset.forName("utf-8"); + + public String translate(String s) throws IOException { + if (numStrings <= 0) return s; + + byte[] bytes = s.getBytes(charset); + byte[] translation = find(bytes); + if (translation == null || translation.length <= 0) return s; + //translations.add(s); + return new String(translation, charset); + } + + private byte[] find(byte[] bytes) throws IOException { + return find(bytes, 0, numStrings); + } + + private byte[] find(byte[] bytes, int minIndex, int maxIndex) throws IOException { + int middleIndex; + while(minIndex != maxIndex) { + if (minIndex+1 == maxIndex) middleIndex = minIndex; + else if (minIndex+2 == maxIndex) middleIndex = minIndex; + else middleIndex = (minIndex + maxIndex) / 2; + + int c = compare(bytes, middleIndex); + if (c == 0) return getTranslatedStringAt(middleIndex); + + if (minIndex+1 == maxIndex) { + return null; + } else if (c > 0) { + maxIndex = middleIndex; + } else { + minIndex = middleIndex+1; + } + } + return null; + } + + private final byte[] buf = new byte[8]; + public final int readIntLE() throws IOException + { + reader.read(buf, 0, 4); + return + (buf[3]) << 24 | + (buf[2]&0xff) << 16 | + (buf[1]&0xff) << 8 | + (buf[0]&0xff); + } + + private void seek(int pos) throws IOException { + reader.reset(); + reader.skip(pos); + } + + private byte[] getTranslatedStringAt(int idx) throws IOException { + seek(offsetTranslatedStrings + idx*8); + int length = readIntLE(); + int offset = readIntLE(); + seek(offset); + byte[] result = new byte[length]; + reader.read(result, 0, length); + return result; + } + + private int compare(byte[] bytes, int idx) throws IOException { + seek(offsetOriginalStrings + idx*8); + int length = readIntLE(); + int offset = readIntLE(); + seek(offset); + int maxLength = bytes.length; + for(int i = 0; i < length; ++i) { + if (i == maxLength) return 1; + int b = reader.read(); + if (b == bytes[i]) continue; + return (b < bytes[i]) ? -1 : 1; + } + if (length < maxLength) return -1; + return 0; + } + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ActorConditionsTypeParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ActorConditionsTypeParser.java index e44ce21ed..6d4e3d322 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ActorConditionsTypeParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ActorConditionsTypeParser.java @@ -2,6 +2,7 @@ package com.gpl.rpg.AndorsTrail.resource.parsers; import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType; import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonFieldNames; import com.gpl.rpg.AndorsTrail.util.Pair; @@ -11,17 +12,19 @@ import org.json.JSONObject; public final class ActorConditionsTypeParser extends JsonCollectionParserFor { private final DynamicTileLoader tileLoader; - - public ActorConditionsTypeParser(final DynamicTileLoader tileLoader) { + private final TranslationLoader translationLoader; + + public ActorConditionsTypeParser(final DynamicTileLoader tileLoader, TranslationLoader translationLoader) { this.tileLoader = tileLoader; - } + this.translationLoader = translationLoader; + } @Override protected Pair parseObject(JSONObject o) throws JSONException { final String conditionTypeID = o.getString(JsonFieldNames.ActorCondition.conditionTypeID); ActorConditionType result = new ActorConditionType( conditionTypeID - ,o.getString(JsonFieldNames.ActorCondition.name) + ,translationLoader.translateActorConditionName(o.getString(JsonFieldNames.ActorCondition.name)) ,ResourceParserUtils.parseImageID(tileLoader, o.getString(JsonFieldNames.ActorCondition.iconID)) ,o.getInt(JsonFieldNames.ActorCondition.category) ,o.optInt(JsonFieldNames.ActorCondition.isStacking) > 0 diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java index c9fc678cb..e1129f1c2 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java @@ -5,6 +5,7 @@ import com.gpl.rpg.AndorsTrail.conversation.Phrase; import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply; import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reward; import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonFieldNames; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonParserFor; @@ -16,8 +17,10 @@ import org.json.JSONObject; import java.util.ArrayList; public final class ConversationListParser extends JsonCollectionParserFor { - - private final JsonParserFor replyParser = new JsonParserFor() { + + private final TranslationLoader translationLoader; + + private final JsonParserFor replyParser = new JsonParserFor() { @Override protected Reply parseObject(JSONObject o) throws JSONException { JSONObject requires = o.optJSONObject(JsonFieldNames.Reply.requires); @@ -35,7 +38,7 @@ public final class ConversationListParser extends JsonCollectionParserFor parseObject(JSONObject o) throws JSONException { final String id = o.getString(JsonFieldNames.Phrase.phraseID); @@ -76,7 +83,7 @@ public final class ConversationListParser extends JsonCollectionParserFor(id, new Phrase( - o.optString(JsonFieldNames.Phrase.message, null) + translationLoader.translateConversationPhrase(o.optString(JsonFieldNames.Phrase.message, null)) , _replies , _rewards )); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemCategoryParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemCategoryParser.java index e14965791..5eab59d39 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemCategoryParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemCategoryParser.java @@ -1,6 +1,7 @@ package com.gpl.rpg.AndorsTrail.resource.parsers; import com.gpl.rpg.AndorsTrail.model.item.ItemCategory; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonFieldNames; import com.gpl.rpg.AndorsTrail.util.Pair; @@ -9,12 +10,19 @@ import org.json.JSONObject; public final class ItemCategoryParser extends JsonCollectionParserFor { - @Override + private final TranslationLoader translationLoader; + + public ItemCategoryParser(TranslationLoader translationLoader) { + + this.translationLoader = translationLoader; + } + + @Override protected Pair parseObject(JSONObject o) throws JSONException { final String id = o.getString(JsonFieldNames.ItemCategory.itemCategoryID); ItemCategory result = new ItemCategory( id - ,o.getString(JsonFieldNames.ItemCategory.name) + ,translationLoader.translateItemCategoryName(o.getString(JsonFieldNames.ItemCategory.name)) ,o.optInt(JsonFieldNames.ItemCategory.actionType, 0) ,o.optInt(JsonFieldNames.ItemCategory.inventorySlot, -1) ,o.optInt(JsonFieldNames.ItemCategory.size, 0) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java index 5826f3ec0..066d2df73 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java @@ -6,6 +6,7 @@ import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnEquip; import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse; import com.gpl.rpg.AndorsTrail.model.item.ItemType; import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonFieldNames; import com.gpl.rpg.AndorsTrail.util.Pair; @@ -15,19 +16,25 @@ import org.json.JSONObject; public final class ItemTypeParser extends JsonCollectionParserFor { private final DynamicTileLoader tileLoader; - private final ItemTraitsParser itemTraitsParser; + private final TranslationLoader translationLoader; + private final ItemTraitsParser itemTraitsParser; private final ItemCategoryCollection itemCategories; - public ItemTypeParser(DynamicTileLoader tileLoader, ActorConditionTypeCollection actorConditionsTypes, ItemCategoryCollection itemCategories) { + public ItemTypeParser( + DynamicTileLoader tileLoader, + ActorConditionTypeCollection actorConditionsTypes, + ItemCategoryCollection itemCategories, + TranslationLoader translationLoader) { this.tileLoader = tileLoader; - this.itemTraitsParser = new ItemTraitsParser(actorConditionsTypes); + this.translationLoader = translationLoader; + this.itemTraitsParser = new ItemTraitsParser(actorConditionsTypes); this.itemCategories = itemCategories; } @Override public Pair parseObject(JSONObject o) throws JSONException { final String id = o.getString(JsonFieldNames.ItemType.itemTypeID); - final String itemTypeName = o.getString(JsonFieldNames.ItemType.name); + final String itemTypeName = translationLoader.translateItemTypeName(o.getString(JsonFieldNames.ItemType.name)); final ItemTraits_OnEquip equipEffect = itemTraitsParser.parseItemTraits_OnEquip(o.optJSONObject(JsonFieldNames.ItemType.equipEffect)); final ItemTraits_OnUse useEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.useEffect)); final ItemTraits_OnUse hitEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.hitEffect)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/MonsterTypeParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/MonsterTypeParser.java index d57cc0e3b..871644fc1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/MonsterTypeParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/MonsterTypeParser.java @@ -7,6 +7,7 @@ import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; import com.gpl.rpg.AndorsTrail.model.item.DropListCollection; import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse; import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonFieldNames; import com.gpl.rpg.AndorsTrail.util.ConstRange; @@ -21,9 +22,15 @@ public final class MonsterTypeParser extends JsonCollectionParserFor(monsterTypeID, new MonsterType( monsterTypeID - , o.getString(JsonFieldNames.Monster.name) + , translationLoader.translateMonsterTypeName(o.getString(JsonFieldNames.Monster.name)) , o.optString(JsonFieldNames.Monster.spawnGroup, monsterTypeID) , exp , droplists.getDropList(o.optString(JsonFieldNames.Monster.droplistID, null)) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/QuestParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/QuestParser.java index b00d67e60..6b074c672 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/QuestParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/QuestParser.java @@ -2,6 +2,7 @@ package com.gpl.rpg.AndorsTrail.resource.parsers; import com.gpl.rpg.AndorsTrail.model.quest.Quest; import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry; +import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonFieldNames; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonParserFor; @@ -14,14 +15,15 @@ import java.util.Collections; import java.util.Comparator; public final class QuestParser extends JsonCollectionParserFor { - private int sortOrder = 0; + private final TranslationLoader translationLoader; + private int sortOrder = 0; private final JsonParserFor questLogEntryParser = new JsonParserFor() { @Override protected QuestLogEntry parseObject(JSONObject o) throws JSONException { return new QuestLogEntry( o.getInt(JsonFieldNames.QuestLogEntry.progress) - ,o.optString(JsonFieldNames.QuestLogEntry.logText, null) + ,translationLoader.translateQuestLogEntry(o.optString(JsonFieldNames.QuestLogEntry.logText, null)) ,o.optInt(JsonFieldNames.QuestLogEntry.rewardExperience, 0) ,o.optInt(JsonFieldNames.QuestLogEntry.finishesQuest, 0) > 0 ); @@ -34,7 +36,11 @@ public final class QuestParser extends JsonCollectionParserFor { } }; - @Override + public QuestParser(TranslationLoader translationLoader) { + this.translationLoader = translationLoader; + } + + @Override protected Pair parseObject(JSONObject o) throws JSONException { final String id = o.getString(JsonFieldNames.Quest.questID); @@ -47,7 +53,7 @@ public final class QuestParser extends JsonCollectionParserFor { return new Pair(id, new Quest( id - , o.getString(JsonFieldNames.Quest.name) + , translationLoader.translateQuestName(o.getString(JsonFieldNames.Quest.name)) , stages_ , o.optInt(JsonFieldNames.Quest.showInLog, 0) > 0 , sortOrder From a74bef815ca1ebb575c33af4e1f7b98a7332020e Mon Sep 17 00:00:00 2001 From: Oskar Wiksten Date: Mon, 11 Feb 2013 16:12:46 +0000 Subject: [PATCH 2/5] Updated translation MO-file parser to read the MO filename from strings.xml. --- AndorsTrail/res/values-de/strings.xml | 5 ++++ AndorsTrail/res/values-fr/strings.xml | 4 +++ AndorsTrail/res/values-it/strings.xml | 5 ++++ AndorsTrail/res/values-ja/strings.xml | 6 ++++ AndorsTrail/res/values-pl/strings.xml | 5 ++++ AndorsTrail/res/values-pt-rBR/strings.xml | 5 ++++ AndorsTrail/res/values-pt/strings.xml | 5 ++++ AndorsTrail/res/values-ru/strings.xml | 4 +++ AndorsTrail/res/values/strings.xml | 1 + .../conversation/ConversationLoader.java | 2 +- .../AndorsTrail/resource/ResourceLoader.java | 2 +- .../resource/TranslationLoader.java | 30 ++++++++++++------- .../resource/parsers/ItemTypeParser.java | 3 +- 13 files changed, 64 insertions(+), 13 deletions(-) diff --git a/AndorsTrail/res/values-de/strings.xml b/AndorsTrail/res/values-de/strings.xml index ac1673f2f..d2ded41e0 100644 --- a/AndorsTrail/res/values-de/strings.xml +++ b/AndorsTrail/res/values-de/strings.xml @@ -557,5 +557,10 @@ Bestätige das Überschreiben von Spielständen Zeigt eine Frage an ob beim Speichern auf einen bereits existierenden Spielstand dieser überschrieben werden soll. + + + + + de.mo diff --git a/AndorsTrail/res/values-fr/strings.xml b/AndorsTrail/res/values-fr/strings.xml index e4aadbd6c..b0073b216 100644 --- a/AndorsTrail/res/values-fr/strings.xml +++ b/AndorsTrail/res/values-fr/strings.xml @@ -485,4 +485,8 @@ Immunise contre les coups critiques Taux de coups critiques : + + + + fr.mo diff --git a/AndorsTrail/res/values-it/strings.xml b/AndorsTrail/res/values-it/strings.xml index 5d1c5b3c1..0fb41e436 100644 --- a/AndorsTrail/res/values-it/strings.xml +++ b/AndorsTrail/res/values-it/strings.xml @@ -320,4 +320,9 @@ 2.0f + + + + it.mo + diff --git a/AndorsTrail/res/values-ja/strings.xml b/AndorsTrail/res/values-ja/strings.xml index f49f62107..a4fac72ce 100644 --- a/AndorsTrail/res/values-ja/strings.xml +++ b/AndorsTrail/res/values-ja/strings.xml @@ -513,4 +513,10 @@ あなたの命中率より %1$d 以上回避率が低い敵に攻撃するたび、その攻撃は %2$d%% の確率で対象に脳震盪(concussion)を起こします。concussionは攻撃に関する戦闘能力を劇的に下げ、対象は有効な攻撃を当てることが難しくなります。 About + + + + + ja.mo + \ No newline at end of file diff --git a/AndorsTrail/res/values-pl/strings.xml b/AndorsTrail/res/values-pl/strings.xml index cd15341e3..c6da50ea4 100644 --- a/AndorsTrail/res/values-pl/strings.xml +++ b/AndorsTrail/res/values-pl/strings.xml @@ -559,5 +559,10 @@ Translated by toudi5-bełchatów Potwierdź nadpisanie gry Zadaje pytanie zawsze, gdy chcesz nadpisać grę na slocie, który jest już zajęty. + + + + + pl.mo diff --git a/AndorsTrail/res/values-pt-rBR/strings.xml b/AndorsTrail/res/values-pt-rBR/strings.xml index df20aacd0..def05f2b1 100644 --- a/AndorsTrail/res/values-pt-rBR/strings.xml +++ b/AndorsTrail/res/values-pt-rBR/strings.xml @@ -559,4 +559,9 @@ Confirma re-escrita de salvamento Pergunta o que deve ser feito caso tente-se gravar sobre um salvamento anterior. + + + + pt-rBR.mo + diff --git a/AndorsTrail/res/values-pt/strings.xml b/AndorsTrail/res/values-pt/strings.xml index 70427713a..53dbba43b 100644 --- a/AndorsTrail/res/values-pt/strings.xml +++ b/AndorsTrail/res/values-pt/strings.xml @@ -475,4 +475,9 @@ Optimized drawing Desactiva esta opção caso apareçam artefactos gráficos. Ao activar esta opção apenas serão redesenhados no écrã os blocos alterados em cada fotograma. + + + + pt.mo + diff --git a/AndorsTrail/res/values-ru/strings.xml b/AndorsTrail/res/values-ru/strings.xml index 0c1373f08..504e64174 100644 --- a/AndorsTrail/res/values-ru/strings.xml +++ b/AndorsTrail/res/values-ru/strings.xml @@ -558,5 +558,9 @@ Перезаписать сохранение Настройка диалога подтверждения при попытке перезаписать сохранение + + + + ru.mo diff --git a/AndorsTrail/res/values/strings.xml b/AndorsTrail/res/values/strings.xml index 77c4f4a10..ba7969781 100644 --- a/AndorsTrail/res/values/strings.xml +++ b/AndorsTrail/res/values/strings.xml @@ -564,6 +564,7 @@ Use item cost (AP): %1$s moves. Combat log + [Quest completed: \"%1$s\"] [Quest updated: \"%1$s\"] diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java index 62ecdf671..e56af5e47 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationLoader.java @@ -21,7 +21,7 @@ public final class ConversationLoader { return conversationCollection.getPhrase(phraseID); } - TranslationLoader translationLoader = new TranslationLoader(r.getAssets()); + TranslationLoader translationLoader = new TranslationLoader(r.getAssets(), r); ConversationListParser conversationListParser = new ConversationListParser(translationLoader); int resourceID = resourceIDsPerPhraseID.get(phraseID); conversationCollection.initialize(conversationListParser, ResourceLoader.readStringFromRaw(r, resourceID)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java index 2bb3dfa59..37a7476a8 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java @@ -42,7 +42,7 @@ public final class ResourceLoader { final int mTileSize = world.tileManager.tileSize; - TranslationLoader translationLoader = new TranslationLoader(r.getAssets()); + TranslationLoader translationLoader = new TranslationLoader(r.getAssets(), r); DynamicTileLoader loader = new DynamicTileLoader(world.tileManager.tileCache); prepareTilesets(loader, mTileSize); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java index 95b3bcdc2..ac2e051b6 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java @@ -1,9 +1,12 @@ package com.gpl.rpg.AndorsTrail.resource; import android.content.res.AssetManager; +import android.content.res.Resources; +import com.gpl.rpg.AndorsTrail.R; import com.gpl.rpg.AndorsTrail.util.L; import java.io.BufferedInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; @@ -11,21 +14,30 @@ import java.nio.charset.Charset; public final class TranslationLoader { private final BinaryMoFileParser parser; - public TranslationLoader(AssetManager mgr) { - BinaryMoFileParser parser = null; + public TranslationLoader(AssetManager mgr, Resources res) { + this.parser = createParser(mgr, res); + } + + private static final String translationDir = "translation" + File.separator; + private static BinaryMoFileParser createParser(AssetManager mgr, Resources res) { + String translationFilename = res.getString(R.string.localize_resources_from_mo_filename); + if (translationFilename == null || translationFilename.length() <= 0) return null; + + translationFilename = translationDir + translationFilename; + try { - InputStream is = mgr.open("messages.mo"); - parser = new BinaryMoFileParser(is); + InputStream is = mgr.open(translationFilename); + return new BinaryMoFileParser(is); } catch (IOException e) { - L.log("ERROR: Reading from translation asset failed: " + e.toString()); + L.log("ERROR: Reading from translation asset \"" + translationFilename + "\" failed: " + e.toString()); + return null; } - this.parser = parser; } private String tr(String s) { if (s == null) return null; - if (s.length() <= 1) return s; if (parser == null) return s; + if (s.length() <= 1) return s; try { //String t = parser.translate(s); //L.log(translations.size() + " : " + s + " -> " + t); @@ -46,14 +58,13 @@ public final class TranslationLoader { public String translateItemCategoryName(String s) { return tr(s); } public String translateActorConditionName(String s) { return tr(s); } public String translateItemTypeName(String s) { return tr(s); } + public String translateItemTypeDescription(String s) {return tr(s); } public String translateMonsterTypeName(String s) { return tr(s); } public String translateQuestName(String s) { return tr(s); } public String translateQuestLogEntry(String s) { return tr(s); } public String translateConversationPhrase(String s) { return tr(s); } public String translateConversationReply(String s) { return tr(s); } - //public static HashSet translations = new HashSet(); - private static final class BinaryMoFileParser { private final InputStream is; private final BufferedInputStream reader; @@ -86,7 +97,6 @@ public final class TranslationLoader { byte[] bytes = s.getBytes(charset); byte[] translation = find(bytes); if (translation == null || translation.length <= 0) return s; - //translations.add(s); return new String(translation, charset); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java index 066d2df73..0863f8552 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ItemTypeParser.java @@ -35,6 +35,7 @@ public final class ItemTypeParser extends JsonCollectionParserFor { public Pair parseObject(JSONObject o) throws JSONException { final String id = o.getString(JsonFieldNames.ItemType.itemTypeID); final String itemTypeName = translationLoader.translateItemTypeName(o.getString(JsonFieldNames.ItemType.name)); + final String description = translationLoader.translateItemTypeDescription(o.optString(JsonFieldNames.ItemType.description, null)); final ItemTraits_OnEquip equipEffect = itemTraitsParser.parseItemTraits_OnEquip(o.optJSONObject(JsonFieldNames.ItemType.equipEffect)); final ItemTraits_OnUse useEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.useEffect)); final ItemTraits_OnUse hitEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.hitEffect)); @@ -46,7 +47,7 @@ public final class ItemTypeParser extends JsonCollectionParserFor { id , ResourceParserUtils.parseImageID(tileLoader, o.getString(JsonFieldNames.ItemType.iconID)) , itemTypeName - , o.optString(JsonFieldNames.ItemType.description, null) + , description , itemCategories.getItemCategory(o.getString(JsonFieldNames.ItemType.category)) , o.optInt(JsonFieldNames.ItemType.displaytype, ItemType.DISPLAYTYPE_ORDINARY) , hasManualPrice From 7672827d1f97d0fe65838f6757356ced7e6d0477 Mon Sep 17 00:00:00 2001 From: Oskar Wiksten Date: Tue, 12 Feb 2013 14:46:46 +0000 Subject: [PATCH 3/5] Update visibility of methods used in unit tests. --- .../gpl/rpg/AndorsTrail/resource/TranslationLoader.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java index ac2e051b6..c941f4dfa 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java @@ -17,14 +17,19 @@ public final class TranslationLoader { public TranslationLoader(AssetManager mgr, Resources res) { this.parser = createParser(mgr, res); } + public TranslationLoader(AssetManager mgr, String filename) { + this.parser = createParser(mgr, filename); + } private static final String translationDir = "translation" + File.separator; private static BinaryMoFileParser createParser(AssetManager mgr, Resources res) { String translationFilename = res.getString(R.string.localize_resources_from_mo_filename); if (translationFilename == null || translationFilename.length() <= 0) return null; - translationFilename = translationDir + translationFilename; + return createParser(mgr, translationDir + translationFilename); + } + private static BinaryMoFileParser createParser(AssetManager mgr, String translationFilename) { try { InputStream is = mgr.open(translationFilename); return new BinaryMoFileParser(is); From 96bc4ec59cc3e0255673a46f502d56a38a3e1384 Mon Sep 17 00:00:00 2001 From: Oskar Wiksten Date: Tue, 25 Jun 2013 01:09:16 +0200 Subject: [PATCH 4/5] Preparation for placing translation files in "assets/" --- AndorsTrail/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/AndorsTrail/.gitignore b/AndorsTrail/.gitignore index e271b24aa..258f986d4 100644 --- a/AndorsTrail/.gitignore +++ b/AndorsTrail/.gitignore @@ -1,7 +1,6 @@ # Android ignores gen/ bin/ -assets/ target/ local.properties From adee44524f6cdac23901f06b61a719486e6794ff Mon Sep 17 00:00:00 2001 From: Oskar Wiksten Date: Wed, 26 Jun 2013 21:55:59 +0200 Subject: [PATCH 5/5] Fix Android Lint warnings. --- .../com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java index c941f4dfa..40632a9ce 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/TranslationLoader.java @@ -9,7 +9,6 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.Charset; public final class TranslationLoader { private final BinaryMoFileParser parser; @@ -94,7 +93,7 @@ public final class TranslationLoader { is.close(); } - private final Charset charset = Charset.forName("utf-8"); + private static final String charset = "utf-8"; public String translate(String s) throws IOException { if (numStrings <= 0) return s;