mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Implement better in-game localization/translation
This commit is contained in:
@@ -1,17 +1,20 @@
|
|||||||
package forge.util;
|
package forge.util;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class CardTranslation {
|
public class CardTranslation {
|
||||||
|
|
||||||
private static Map <String, String> translatednames;
|
private static Map <String, String> translatednames;
|
||||||
private static Map <String, String> translatedtypes;
|
private static Map <String, String> translatedtypes;
|
||||||
private static Map <String, String> translatedoracles;
|
private static Map <String, String> translatedoracles;
|
||||||
|
private static Map <String, List <Pair <String, String> > > oracleMappings;
|
||||||
|
private static Map <String, String> translatedCaches;
|
||||||
private static String languageSelected = "en-US";
|
private static String languageSelected = "en-US";
|
||||||
|
|
||||||
private static void readTranslationFile(String language, String languagesDirectory) {
|
private static void readTranslationFile(String language, String languagesDirectory) {
|
||||||
@@ -27,7 +30,7 @@ public class CardTranslation {
|
|||||||
translatedtypes.put(matches[0], matches[2]);
|
translatedtypes.put(matches[0], matches[2]);
|
||||||
}
|
}
|
||||||
if (matches.length >= 4) {
|
if (matches.length >= 4) {
|
||||||
translatedoracles.put(matches[0], matches[3].replace("\\n", "\n\n"));
|
translatedoracles.put(matches[0], matches[3].replace("\\n", "\r\n\r\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -89,7 +92,101 @@ public class CardTranslation {
|
|||||||
translatednames = new HashMap<>();
|
translatednames = new HashMap<>();
|
||||||
translatedtypes = new HashMap<>();
|
translatedtypes = new HashMap<>();
|
||||||
translatedoracles = new HashMap<>();
|
translatedoracles = new HashMap<>();
|
||||||
|
oracleMappings = new HashMap<>();
|
||||||
|
translatedCaches = new HashMap<>();
|
||||||
readTranslationFile(languageSelected, languagesDirectory);
|
readTranslationFile(languageSelected, languagesDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static String replaceCardName(String language, String name, String toracle) {
|
||||||
|
String nickName = language.equals("en-US") ? Lang.getEnglishInstance().getNickName(name) : Lang.getInstance().getNickName(name);
|
||||||
|
String result = TextUtil.fastReplace(toracle, name, "CARDNAME");
|
||||||
|
if (!nickName.equals(name)) {
|
||||||
|
result = TextUtil.fastReplace(result, nickName, "NICKNAME");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void buildOracleMapping(String faceName, String oracleText) {
|
||||||
|
if (!needsTranslation() || oracleMappings.containsKey(faceName)) return;
|
||||||
|
String translatedName = getTranslatedName(faceName);
|
||||||
|
String translatedText = getTranslatedOracle(faceName);
|
||||||
|
List <Pair <String, String> > mapping = new ArrayList<>();
|
||||||
|
String [] splitOracleText = oracleText.split("\\\\n");
|
||||||
|
String [] splitTranslatedText = translatedText.split("\r\n\r\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < splitOracleText.length && i < splitTranslatedText.length; i++) {
|
||||||
|
String toracle = replaceCardName("en-US", faceName, splitOracleText[i]);
|
||||||
|
String ttranslated = replaceCardName(languageSelected, translatedName, splitTranslatedText[i]);
|
||||||
|
// Remove reminder text in English oracle text unless entire line is reminder text
|
||||||
|
if (!toracle.startsWith("(")) {
|
||||||
|
toracle = toracle.replaceAll("\\(.*\\)", "");
|
||||||
|
}
|
||||||
|
mapping.add(Pair.of(toracle, ttranslated));
|
||||||
|
}
|
||||||
|
oracleMappings.put(faceName, mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String translateMultipleDescriptionText(String descText, String cardName) {
|
||||||
|
if (!needsTranslation()) return descText;
|
||||||
|
String [] splitDescText = descText.split("\r\n");
|
||||||
|
String result = descText;
|
||||||
|
for (String text : splitDescText) {
|
||||||
|
if (text.isEmpty()) continue;
|
||||||
|
String translated = translateSingleDescriptionText(text, cardName);
|
||||||
|
if (!text.equals(translated)) {
|
||||||
|
result = TextUtil.fastReplace(result, text, translated);
|
||||||
|
} else {
|
||||||
|
// keywords maybe combined into one line, split them and try translate again
|
||||||
|
String [] splitKeywords = text.split(", ");
|
||||||
|
if (splitKeywords.length <= 1) continue;
|
||||||
|
for (String keyword : splitKeywords) {
|
||||||
|
if (keyword.contains(" ")) continue;
|
||||||
|
translated = translateSingleDescriptionText(keyword, cardName);
|
||||||
|
if (!keyword.equals(translated)) {
|
||||||
|
result = TextUtil.fastReplace(result, keyword, translated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String translateSingleDescriptionText(String descText, String cardName) {
|
||||||
|
if (!needsTranslation()) return descText;
|
||||||
|
if (translatedCaches.containsKey(descText)) return translatedCaches.get(descText);
|
||||||
|
|
||||||
|
List <Pair <String, String> > mapping = oracleMappings.get(cardName);
|
||||||
|
if (mapping == null) return descText;
|
||||||
|
String result = descText;
|
||||||
|
if (!mapping.isEmpty()) {
|
||||||
|
result = translateSingleIngameText(descText, mapping);
|
||||||
|
}
|
||||||
|
translatedCaches.put(descText, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String translateSingleIngameText(String descText, List <Pair <String, String> > mapping) {
|
||||||
|
String tcompare = descText.startsWith("(") ? descText : descText.replaceAll("\\(.*\\)", "");
|
||||||
|
|
||||||
|
// Use Levenshtein Distance to find matching oracle text and replace it with translated text
|
||||||
|
int candidateIndex = mapping.size();
|
||||||
|
int minDistance = tcompare.length();
|
||||||
|
for (int i = 0; i < mapping.size(); i++) {
|
||||||
|
String toracle = mapping.get(i).getLeft();
|
||||||
|
int threshold = Math.min(toracle.length(), tcompare.length()) / 3;
|
||||||
|
int distance = StringUtils.getLevenshteinDistance(toracle, tcompare, threshold);
|
||||||
|
if (distance != -1 && distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
|
candidateIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidateIndex < mapping.size()) {
|
||||||
|
return mapping.get(candidateIndex).getRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
return descText;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import com.google.common.collect.Lists;
|
|||||||
public abstract class Lang {
|
public abstract class Lang {
|
||||||
|
|
||||||
private static Lang instance;
|
private static Lang instance;
|
||||||
|
private static Lang englishInstance;
|
||||||
|
|
||||||
protected String languageCode;
|
protected String languageCode;
|
||||||
protected String countryCode;
|
protected String countryCode;
|
||||||
@@ -41,11 +42,20 @@ public abstract class Lang {
|
|||||||
}
|
}
|
||||||
instance.languageCode = language;
|
instance.languageCode = language;
|
||||||
instance.countryCode = country;
|
instance.countryCode = country;
|
||||||
|
|
||||||
|
// Create english instance for internal usage
|
||||||
|
englishInstance = new LangEnglish();
|
||||||
|
englishInstance.languageCode = "en";
|
||||||
|
englishInstance.countryCode = "US";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Lang getInstance() {
|
public static Lang getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Lang getEnglishInstance() {
|
||||||
|
return englishInstance;
|
||||||
|
}
|
||||||
|
|
||||||
protected Lang() {
|
protected Lang() {
|
||||||
}
|
}
|
||||||
@@ -170,4 +180,6 @@ public abstract class Lang {
|
|||||||
}
|
}
|
||||||
return Integer.toString(n);
|
return Integer.toString(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract String getNickName(final String name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,9 @@ public class LangChinese extends Lang {
|
|||||||
return getPossesive(owner) + object;
|
return getPossesive(owner) + object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNickName(final String name) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,8 @@ public class LangEnglish extends Lang {
|
|||||||
return getPossesive(owner) + " " + object;
|
return getPossesive(owner) + " " + object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNickName(final String name) {
|
||||||
|
return name.split(", ")[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,4 +26,10 @@ public class LangGerman extends Lang {
|
|||||||
return getPossesive(owner) + " " + object;
|
return getPossesive(owner) + " " + object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNickName(final String name) {
|
||||||
|
return name.split(", ")[0];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,4 +23,9 @@ public class LangItalian extends Lang {
|
|||||||
return getPossesive(owner) + " " + object;
|
return getPossesive(owner) + " " + object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNickName(final String name) {
|
||||||
|
return name.split(", ")[0];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,11 @@ public class LangJapanese extends Lang {
|
|||||||
return getPossesive(owner) + object;
|
return getPossesive(owner) + object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNickName(final String name) {
|
||||||
|
String [] splitName = name.split("、");
|
||||||
|
if (splitName.length > 1) return splitName[1];
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,4 +23,9 @@ public class LangSpanish extends Lang {
|
|||||||
return getPossesive(owner) + " " + object;
|
return getPossesive(owner) + " " + object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNickName(final String name) {
|
||||||
|
return name.split(", ")[0];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public abstract class SpellAbilityEffect {
|
|||||||
// by typing "SpellDescription" they want to bypass the Effect's string builder
|
// by typing "SpellDescription" they want to bypass the Effect's string builder
|
||||||
if ("SpellDescription".equalsIgnoreCase(stackDesc)) {
|
if ("SpellDescription".equalsIgnoreCase(stackDesc)) {
|
||||||
if (params.get("SpellDescription") != null) {
|
if (params.get("SpellDescription") != null) {
|
||||||
sb.append(params.get("SpellDescription"));
|
sb.append(CardTranslation.translateSingleDescriptionText(params.get("SpellDescription"), sa.getHostCard().getName()));
|
||||||
}
|
}
|
||||||
if (sa.getTargets() != null && !sa.getTargets().isEmpty()) {
|
if (sa.getTargets() != null && !sa.getTargets().isEmpty()) {
|
||||||
sb.append(" (Targeting: ").append(sa.getTargets()).append(")");
|
sb.append(" (Targeting: ").append(sa.getTargets()).append(")");
|
||||||
@@ -98,7 +98,7 @@ public abstract class SpellAbilityEffect {
|
|||||||
} else {
|
} else {
|
||||||
final String conditionDesc = sa.getParam("ConditionDescription");
|
final String conditionDesc = sa.getParam("ConditionDescription");
|
||||||
final String afterDesc = sa.getParam("AfterDescription");
|
final String afterDesc = sa.getParam("AfterDescription");
|
||||||
final String baseDesc = this.getStackDescription(sa);
|
final String baseDesc = CardTranslation.translateSingleDescriptionText(this.getStackDescription(sa), sa.getHostCard().getName());
|
||||||
if (conditionDesc != null) {
|
if (conditionDesc != null) {
|
||||||
sb.append(conditionDesc).append(" ");
|
sb.append(conditionDesc).append(" ");
|
||||||
}
|
}
|
||||||
@@ -131,8 +131,8 @@ public abstract class SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String currentName = (sa.getHostCard().getName());
|
String currentName = (sa.getHostCard().getName());
|
||||||
String substitutedDesc = TextUtil.fastReplace(sb.toString(), "CARDNAME", currentName);
|
String substitutedDesc = TextUtil.fastReplace(sb.toString(), "CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||||
substitutedDesc = TextUtil.fastReplace(substitutedDesc, "NICKNAME", currentName.split(",")[0]);
|
substitutedDesc = TextUtil.fastReplace(substitutedDesc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||||
return substitutedDesc;
|
return substitutedDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.util.CardTranslation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for this type.
|
* TODO: Write javadoc for this type.
|
||||||
@@ -13,6 +14,6 @@ public class PermanentNoncreatureEffect extends PermanentEffect {
|
|||||||
public String getStackDescription(final SpellAbility sa) {
|
public String getStackDescription(final SpellAbility sa) {
|
||||||
final Card sourceCard = sa.getHostCard();
|
final Card sourceCard = sa.getHostCard();
|
||||||
//CardView toString return translated name,don't need call CardTranslation.getTranslatedName in this.
|
//CardView toString return translated name,don't need call CardTranslation.getTranslatedName in this.
|
||||||
return sourceCard.getName();
|
return CardTranslation.getTranslatedName(sourceCard.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2081,7 +2081,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
sbLong.append("\r\n");
|
sbLong.append("\r\n");
|
||||||
}
|
}
|
||||||
sb.append(sbLong);
|
sb.append(sbLong);
|
||||||
return sb.toString();
|
return CardTranslation.translateMultipleDescriptionText(sb.toString(), getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getTextForKwCantBeBlockedByAmount(final String keyword) {
|
private static String getTextForKwCantBeBlockedByAmount(final String keyword) {
|
||||||
@@ -2119,7 +2119,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
while (result.endsWith("\r\n")) {
|
while (result.endsWith("\r\n")) {
|
||||||
result = result.substring(0, result.length() - 2);
|
result = result.substring(0, result.length() - 2);
|
||||||
}
|
}
|
||||||
return TextUtil.fastReplace(result, "CARDNAME", state.getName());
|
return TextUtil.fastReplace(result, "CARDNAME", CardTranslation.getTranslatedName(state.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monstrous) {
|
if (monstrous) {
|
||||||
@@ -2140,7 +2140,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
for (final ReplacementEffect replacementEffect : state.getReplacementEffects()) {
|
for (final ReplacementEffect replacementEffect : state.getReplacementEffects()) {
|
||||||
if (!replacementEffect.isSecondary()) {
|
if (!replacementEffect.isSecondary()) {
|
||||||
String text = replacementEffect.getDescription();
|
String text = replacementEffect.getDescription();
|
||||||
if (text.contains("enters the battlefield")) {
|
// Get original description since text might be translated
|
||||||
|
if (replacementEffect.hasParam("Description") &&
|
||||||
|
replacementEffect.getParam("Description").contains("enters the battlefield")) {
|
||||||
sb.append(text).append("\r\n");
|
sb.append(text).append("\r\n");
|
||||||
} else {
|
} else {
|
||||||
replacementEffects.append(text).append("\r\n");
|
replacementEffects.append(text).append("\r\n");
|
||||||
@@ -2226,8 +2228,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
|
|
||||||
// add Adventure to AbilityText
|
// add Adventure to AbilityText
|
||||||
if (sa.isAdventure() && state.getView().getState().equals(CardStateName.Original)) {
|
if (sa.isAdventure() && state.getView().getState().equals(CardStateName.Original)) {
|
||||||
|
CardState advState = getState(CardStateName.Adventure);
|
||||||
StringBuilder sbSA = new StringBuilder();
|
StringBuilder sbSA = new StringBuilder();
|
||||||
sbSA.append("Adventure — ").append(getState(CardStateName.Adventure).getName());
|
sbSA.append(Localizer.getInstance().getMessage("lblAdventure"));
|
||||||
|
sbSA.append(" — ").append(CardTranslation.getTranslatedName(advState.getName()));
|
||||||
sbSA.append(" ").append(sa.getPayCosts().toSimpleString());
|
sbSA.append(" ").append(sa.getPayCosts().toSimpleString());
|
||||||
sbSA.append(": ");
|
sbSA.append(": ");
|
||||||
sbSA.append(sAbility);
|
sbSA.append(sAbility);
|
||||||
@@ -2299,7 +2303,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
start = sb.lastIndexOf(s);
|
start = sb.lastIndexOf(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
String desc = TextUtil.fastReplace(sb.toString(), "CARDNAME", state.getName());
|
String desc = TextUtil.fastReplace(sb.toString(), "CARDNAME", CardTranslation.getTranslatedName(state.getName()));
|
||||||
if (getEffectSource() != null) {
|
if (getEffectSource() != null) {
|
||||||
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getEffectSource().getName());
|
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getEffectSource().getName());
|
||||||
}
|
}
|
||||||
@@ -2485,7 +2489,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(sbBefore);
|
sb.append(CardTranslation.translateMultipleDescriptionText(sbBefore.toString(), state.getName()));
|
||||||
|
|
||||||
// add Spells there to main StringBuilder
|
// add Spells there to main StringBuilder
|
||||||
sb.append(strSpell);
|
sb.append(strSpell);
|
||||||
@@ -2514,13 +2518,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(sbAfter);
|
sb.append(CardTranslation.translateMultipleDescriptionText(sbAfter.toString(), state.getName()));
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatSpellAbility(final SpellAbility sa) {
|
private String formatSpellAbility(final SpellAbility sa) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append(sa.toString()).append("\r\n");
|
sb.append(sa.toString()).append("\r\n\r\n");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import forge.game.trigger.TriggerHandler;
|
|||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.util.CardTranslation;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -354,6 +355,10 @@ public class CardFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void readCardFace(Card c, ICardFace face) {
|
private static void readCardFace(Card c, ICardFace face) {
|
||||||
|
// Build English oracle and translated oracle mapping
|
||||||
|
if (c.getId() >= 0) {
|
||||||
|
CardTranslation.buildOracleMapping(face.getName(), face.getOracleText());
|
||||||
|
}
|
||||||
|
|
||||||
// Name first so Senty has the Card name
|
// Name first so Senty has the Card name
|
||||||
c.setName(face.getName());
|
c.setName(face.getName());
|
||||||
|
|||||||
@@ -591,14 +591,8 @@ public class CardView extends GameEntityView {
|
|||||||
if (translationsText != null) {
|
if (translationsText != null) {
|
||||||
tname = translationsText.get("name");
|
tname = translationsText.get("name");
|
||||||
taltname = translationsText.get("altname");
|
taltname = translationsText.get("altname");
|
||||||
|
toracle = translationsText.get("oracle");
|
||||||
// TODO: Translate for cloned or mutated cards
|
taltoracle = translationsText.get("altoracle");
|
||||||
// For now, don't translate oracles if the card is a cloned or mutated
|
|
||||||
if (((String) get(TrackableProperty.Cloner)).isEmpty() &&
|
|
||||||
((String) get(TrackableProperty.MergedCards)).isEmpty()) {
|
|
||||||
toracle = translationsText.get("oracle");
|
|
||||||
taltoracle = translationsText.get("altoracle");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSplitCard()) {
|
if (isSplitCard()) {
|
||||||
@@ -629,18 +623,7 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String rulesText = state.getRulesText();
|
final String rulesText = state.getRulesText();
|
||||||
if (!toracle.isEmpty() && !isFaceDown()) {
|
if (!rulesText.isEmpty()) {
|
||||||
if (isSplitCard()) {
|
|
||||||
sb.append("(").append(tname).append(") ");
|
|
||||||
sb.append(toracle);
|
|
||||||
sb.append("\r\n\r\n");
|
|
||||||
sb.append("(").append(taltname).append(") ");
|
|
||||||
sb.append(taltoracle);
|
|
||||||
} else {
|
|
||||||
sb.append(toracle);
|
|
||||||
}
|
|
||||||
sb.append("\r\n\r\n");
|
|
||||||
} else if (!rulesText.isEmpty()) {
|
|
||||||
sb.append(rulesText).append("\r\n\r\n");
|
sb.append(rulesText).append("\r\n\r\n");
|
||||||
}
|
}
|
||||||
if (isCommander()) {
|
if (isCommander()) {
|
||||||
@@ -648,15 +631,13 @@ public class CardView extends GameEntityView {
|
|||||||
sb.append(getOwner().getCommanderInfo(this)).append("\r\n");
|
sb.append(getOwner().getCommanderInfo(this)).append("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toracle.isEmpty()) {
|
if (isSplitCard() && !isFaceDown() && getZone() != ZoneType.Stack) {
|
||||||
if (isSplitCard() && !isFaceDown() && getZone() != ZoneType.Stack) {
|
sb.append("(").append(getLeftSplitState().getName()).append(") ");
|
||||||
sb.append("(").append(getLeftSplitState().getName()).append(") ");
|
sb.append(getLeftSplitState().getAbilityText());
|
||||||
sb.append(getLeftSplitState().getAbilityText());
|
sb.append("\r\n\r\n").append("(").append(getRightSplitState().getName()).append(") ");
|
||||||
sb.append("\r\n\r\n").append("(").append(getRightSplitState().getName()).append(") ");
|
sb.append(getRightSplitState().getAbilityText());
|
||||||
sb.append(getRightSplitState().getAbilityText());
|
} else {
|
||||||
} else {
|
sb.append(state.getAbilityText());
|
||||||
sb.append(state.getAbilityText());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String nonAbilityText = get(TrackableProperty.NonAbilityText);
|
String nonAbilityText = get(TrackableProperty.NonAbilityText);
|
||||||
@@ -1093,7 +1074,7 @@ public class CardView extends GameEntityView {
|
|||||||
return get(TrackableProperty.OracleText);
|
return get(TrackableProperty.OracleText);
|
||||||
}
|
}
|
||||||
void updateOracleText(Card c) {
|
void updateOracleText(Card c) {
|
||||||
set(TrackableProperty.OracleText, c.getOracleText().replace("\\n", "\r\n").trim());
|
set(TrackableProperty.OracleText, c.getOracleText().replace("\\n", "\r\n\r\n").trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRulesText() {
|
public String getRulesText() {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
import forge.util.Localizer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Class CostExile.
|
* The Class CostExile.
|
||||||
@@ -89,32 +88,32 @@ public class CostExile extends CostPartWithList {
|
|||||||
|
|
||||||
if (this.payCostFromSource()) {
|
if (this.payCostFromSource()) {
|
||||||
if (!this.from.equals(ZoneType.Battlefield)) {
|
if (!this.from.equals(ZoneType.Battlefield)) {
|
||||||
return Localizer.getInstance().getMessage("lblExileTargetsFromYourZone", this.getType(), this.from.getTranslatedName());
|
return String.format("Exile %s from your %s", this.getType(), this.from.name());
|
||||||
}
|
}
|
||||||
return Localizer.getInstance().getMessage("lblExileTarget", this.getType());
|
return String.format("Exile %s", this.getType());
|
||||||
} else if (this.getType().equals("All")) {
|
} else if (this.getType().equals("All")) {
|
||||||
return Localizer.getInstance().getMessage("lblExileAllCardsFromYourZone", this.from.getTranslatedName());
|
return String.format("Exile all cards from your %s", this.from.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.from.equals(ZoneType.Battlefield)) {
|
if (this.from.equals(ZoneType.Battlefield)) {
|
||||||
if (!this.payCostFromSource()) {
|
if (!this.payCostFromSource()) {
|
||||||
return Localizer.getInstance().getMessage("lblExileTargetsYourControl", Cost.convertAmountTypeToWords(i, this.getAmount(), desc));
|
return String.format("Exile %s you control", Cost.convertAmountTypeToWords(i, this.getAmount(), desc));
|
||||||
}
|
}
|
||||||
return Localizer.getInstance().getMessage("lblExileTarget", Cost.convertAmountTypeToWords(i, this.getAmount(), desc));
|
return String.format("Exile %s", Cost.convertAmountTypeToWords(i, this.getAmount(), desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!desc.equals("Card") && !desc.endsWith("card")) {
|
if (!desc.equals("Card") && !desc.endsWith("card")) {
|
||||||
if (this.sameZone) {
|
if (this.sameZone) {
|
||||||
return Localizer.getInstance().getMessage("lblExileNCardFromSameZone", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.getTranslatedName());
|
return String.format("Exile card %s from the same %s", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.name());
|
||||||
}
|
}
|
||||||
return Localizer.getInstance().getMessage("lblExileNCardFromYourZone", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.getTranslatedName());
|
return String.format("Exile card %s from your %s", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.sameZone) {
|
if (this.sameZone) {
|
||||||
return Localizer.getInstance().getMessage("lblExileNTargetFromSameZone", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.getTranslatedName());
|
return String.format("Exile %s from the same %s", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Localizer.getInstance().getMessage("lblExileTargetsFromYourZone", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.getTranslatedName());
|
return String.format("Exile %s from your %s", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), this.from.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.util.CardTranslation;
|
||||||
|
import forge.util.Lang;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -214,15 +216,13 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
|||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
if (hasParam("Description") && !this.isSuppressed()) {
|
if (hasParam("Description") && !this.isSuppressed()) {
|
||||||
String desc = AbilityUtils.applyDescriptionTextChangeEffects(getParam("Description"), this);
|
String desc = AbilityUtils.applyDescriptionTextChangeEffects(getParam("Description"), this);
|
||||||
if (desc.contains("CARDNAME")) {
|
String currentName = getHostCard().getName();
|
||||||
desc = TextUtil.fastReplace(desc, "CARDNAME", getHostCard().toString());
|
desc = CardTranslation.translateSingleDescriptionText(desc, currentName);
|
||||||
}
|
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||||
|
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||||
if (desc.contains("EFFECTSOURCE")) {
|
if (desc.contains("EFFECTSOURCE")) {
|
||||||
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString());
|
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString());
|
||||||
}
|
}
|
||||||
if (desc.contains("NICKNAME")) {
|
|
||||||
desc = TextUtil.fastReplace(desc, "NICKNAME", getHostCard().toString().split(",")[0]);
|
|
||||||
}
|
|
||||||
return desc;
|
return desc;
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ import forge.game.trigger.TriggerType;
|
|||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
import forge.util.CardTranslation;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
|
import forge.util.Lang;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -822,8 +824,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
String desc = node.getDescription();
|
String desc = node.getDescription();
|
||||||
if (node.getHostCard() != null) {
|
if (node.getHostCard() != null) {
|
||||||
desc = TextUtil.fastReplace(desc, "CARDNAME", node.getHostCard().getName());
|
String currentName = node.getHostCard().getName();
|
||||||
desc = TextUtil.fastReplace(desc,"NICKNAME",node.getHostCard().getName().split(",")[0]);
|
desc = CardTranslation.translateMultipleDescriptionText(desc, currentName);
|
||||||
|
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||||
|
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||||
if (node.getOriginalHost() != null) {
|
if (node.getOriginalHost() != null) {
|
||||||
desc = TextUtil.fastReplace(desc, "ORIGINALHOST", node.getOriginalHost().getName());
|
desc = TextUtil.fastReplace(desc, "ORIGINALHOST", node.getOriginalHost().getName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ import forge.game.player.Player;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.CardTranslation;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
|
import forge.util.Lang;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
@@ -214,9 +216,10 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
|
|||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
if (hasParam("Description") && !this.isSuppressed()) {
|
if (hasParam("Description") && !this.isSuppressed()) {
|
||||||
String desc = getParam("Description");
|
String currentName = this.hostCard.getName();
|
||||||
desc = TextUtil.fastReplace(desc, "CARDNAME", this.hostCard.getName());
|
String desc = CardTranslation.translateSingleDescriptionText(getParam("Description"), currentName);
|
||||||
desc = TextUtil.fastReplace(desc, "NICKNAME", this.hostCard.getName().split(",")[0]);
|
desc = TextUtil.fastReplace(desc, "CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||||
|
desc = TextUtil.fastReplace(desc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import java.util.*;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import forge.util.CardTranslation;
|
||||||
|
import forge.util.Lang;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,9 +126,13 @@ public abstract class Trigger extends TriggerReplacementBase {
|
|||||||
if (hasParam("TriggerDescription") && !this.isSuppressed()) {
|
if (hasParam("TriggerDescription") && !this.isSuppressed()) {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String currentName = (getHostCard().getName());
|
String currentName = getHostCard().getName();
|
||||||
String desc1 = TextUtil.fastReplace(getParam("TriggerDescription"),"CARDNAME", currentName);
|
String desc = getParam("TriggerDescription");
|
||||||
String desc = TextUtil.fastReplace(desc1,"NICKNAME", currentName.split(",")[0]);
|
if (!desc.contains("ABILITY")) {
|
||||||
|
desc = CardTranslation.translateSingleDescriptionText(getParam("TriggerDescription"), currentName);
|
||||||
|
desc = TextUtil.fastReplace(desc,"CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||||
|
desc = TextUtil.fastReplace(desc,"NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||||
|
}
|
||||||
if (getHostCard().getEffectSource() != null) {
|
if (getHostCard().getEffectSource() != null) {
|
||||||
if(active)
|
if(active)
|
||||||
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString());
|
desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", getHostCard().getEffectSource().toString());
|
||||||
@@ -198,6 +204,11 @@ public abstract class Trigger extends TriggerReplacementBase {
|
|||||||
saDesc = "<take no action>"; // printed in case nothing is chosen for the ability (e.g. Charm with Up to X)
|
saDesc = "<take no action>"; // printed in case nothing is chosen for the ability (e.g. Charm with Up to X)
|
||||||
}
|
}
|
||||||
result = TextUtil.fastReplace(result, "ABILITY", saDesc);
|
result = TextUtil.fastReplace(result, "ABILITY", saDesc);
|
||||||
|
|
||||||
|
String currentName = sa.getHostCard().getName();
|
||||||
|
result = CardTranslation.translateMultipleDescriptionText(result, currentName);
|
||||||
|
result = TextUtil.fastReplace(result,"CARDNAME", CardTranslation.getTranslatedName(currentName));
|
||||||
|
result = TextUtil.fastReplace(result,"NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class SimulationTestCase extends TestCase {
|
|||||||
@Override
|
@Override
|
||||||
public Void apply(ForgePreferences preferences) {
|
public Void apply(ForgePreferences preferences) {
|
||||||
preferences.setPref(FPref.LOAD_CARD_SCRIPTS_LAZILY, false);
|
preferences.setPref(FPref.LOAD_CARD_SCRIPTS_LAZILY, false);
|
||||||
|
preferences.setPref(FPref.UI_LANGUAGE, "en-US");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@ lblOtherFormats=Andere Formate...
|
|||||||
lblChooseSets=Wähle Sets...
|
lblChooseSets=Wähle Sets...
|
||||||
#HistoricFormatSelect.java
|
#HistoricFormatSelect.java
|
||||||
lblChooseFormat=Wähle Format
|
lblChooseFormat=Wähle Format
|
||||||
|
#Card.java
|
||||||
|
lblAdventure=Adventure
|
||||||
#TriggerAdapt.java
|
#TriggerAdapt.java
|
||||||
lblAdapt=Adaptieren
|
lblAdapt=Adaptieren
|
||||||
#TriggerAttached.java
|
#TriggerAttached.java
|
||||||
@@ -2286,14 +2288,6 @@ lblCostPaymentInvalid=Bezahlung der Kosten unmöglich
|
|||||||
lblSelectATargetToTap=Wähle ein(e) {0} zum Tappen (noch {1})
|
lblSelectATargetToTap=Wähle ein(e) {0} zum Tappen (noch {1})
|
||||||
lblSelectATargetToUntap=Wähle ein(e) {0} zum Enttappen (noch {1})
|
lblSelectATargetToUntap=Wähle ein(e) {0} zum Enttappen (noch {1})
|
||||||
lblUnattachCardConfirm=Löse {0}?
|
lblUnattachCardConfirm=Löse {0}?
|
||||||
#CostExile.java
|
|
||||||
lblExileTargetsFromYourZone=Schicke {0} von deiner/deinem {1} ins Exil
|
|
||||||
lblExileTarget=Schicke {0} ins Exil
|
|
||||||
lblExileAllCardsFromYourZone=Schicke alle Karten aus deiner/deinem {0} ins Exil
|
|
||||||
lblExileTargetsYourControl=Schicke {0}, welche du kontrollierst, ins Exil
|
|
||||||
lblExileNCardFromSameZone=Schicke Karte {0} der/dem gleichen {1} ins Exil
|
|
||||||
lblExileNCardFromYourZone=Schicke Karte {0} von deiner/deinem {1} ins Exil
|
|
||||||
lblExileNTargetFromSameZone=Schicke {0} der/dem gleichen {1} ins Exil
|
|
||||||
#ReplacementHandler.java
|
#ReplacementHandler.java
|
||||||
lblChooseFirstApplyReplacementEffect=Welchen Ersatzeffekt zuerst anwenden?
|
lblChooseFirstApplyReplacementEffect=Welchen Ersatzeffekt zuerst anwenden?
|
||||||
lblApplyCardReplacementEffectToCardConfirm=Wende Ersatzeffekt von {0} auf {1} an?\r\n{2}
|
lblApplyCardReplacementEffectToCardConfirm=Wende Ersatzeffekt von {0} auf {1} an?\r\n{2}
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@ lblOtherFormats=Other Formats
|
|||||||
lblChooseSets=Choose Sets
|
lblChooseSets=Choose Sets
|
||||||
#HistoricFormatSelect.java
|
#HistoricFormatSelect.java
|
||||||
lblChooseFormat=Choose Format
|
lblChooseFormat=Choose Format
|
||||||
|
#Card.java
|
||||||
|
lblAdventure=Adventure
|
||||||
#TriggerAdapt.java
|
#TriggerAdapt.java
|
||||||
lblAdapt=Adapt
|
lblAdapt=Adapt
|
||||||
#TriggerAttached.java
|
#TriggerAttached.java
|
||||||
@@ -2285,14 +2287,6 @@ lblCostPaymentInvalid=Cost payment invalid
|
|||||||
lblSelectATargetToTap=Select a {0} to tap ({1} left)
|
lblSelectATargetToTap=Select a {0} to tap ({1} left)
|
||||||
lblSelectATargetToUntap=Select a {0} to untap ({1} left)
|
lblSelectATargetToUntap=Select a {0} to untap ({1} left)
|
||||||
lblUnattachCardConfirm=Unattach {0}?
|
lblUnattachCardConfirm=Unattach {0}?
|
||||||
#CostExile.java
|
|
||||||
lblExileTargetsFromYourZone=Exile {0} from your {1}
|
|
||||||
lblExileTarget=Exile {0}
|
|
||||||
lblExileAllCardsFromYourZone=Exile all cards from your {0}
|
|
||||||
lblExileTargetsYourControl=Exile {0} you control
|
|
||||||
lblExileNCardFromSameZone=Exile card {0} from the same {1}
|
|
||||||
lblExileNCardFromYourZone=Exile card {0} from your {1}
|
|
||||||
lblExileNTargetFromSameZone=Exile {0} from the same {1}
|
|
||||||
#ReplacementHandler.java
|
#ReplacementHandler.java
|
||||||
lblChooseFirstApplyReplacementEffect=Choose a replacement effect to apply first.
|
lblChooseFirstApplyReplacementEffect=Choose a replacement effect to apply first.
|
||||||
lblApplyCardReplacementEffectToCardConfirm=Apply replacement effect of {0} to {1}?\r\n{2}
|
lblApplyCardReplacementEffectToCardConfirm=Apply replacement effect of {0} to {1}?\r\n{2}
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@ lblOtherFormats=Otros formatos...
|
|||||||
lblChooseSets=Selecciona ediciones...
|
lblChooseSets=Selecciona ediciones...
|
||||||
#HistoricFormatSelect.java
|
#HistoricFormatSelect.java
|
||||||
lblChooseFormat=Selecciona formato
|
lblChooseFormat=Selecciona formato
|
||||||
|
#Card.java
|
||||||
|
lblAdventure=Adventure
|
||||||
#TriggerAdapt.java
|
#TriggerAdapt.java
|
||||||
lblAdapt=Adaptar
|
lblAdapt=Adaptar
|
||||||
#TriggerAttached.java
|
#TriggerAttached.java
|
||||||
@@ -2284,14 +2286,6 @@ lblCostPaymentInvalid=Pago del coste no válido
|
|||||||
lblSelectATargetToTap=Selecciona un/a {0} para girar ({1} pendiente)
|
lblSelectATargetToTap=Selecciona un/a {0} para girar ({1} pendiente)
|
||||||
lblSelectATargetToUntap=Selecciona un/a {0} para enderezar ({1} pendiente)
|
lblSelectATargetToUntap=Selecciona un/a {0} para enderezar ({1} pendiente)
|
||||||
lblUnattachCardConfirm=¿Desanexar {0}?
|
lblUnattachCardConfirm=¿Desanexar {0}?
|
||||||
#CostExile.java
|
|
||||||
lblExileTargetsFromYourZone=Exiliar {0} de tu {1}
|
|
||||||
lblExileTarget=Exiliar {0}
|
|
||||||
lblExileAllCardsFromYourZone=Exilia todas las cartas de tu {0}
|
|
||||||
lblExileTargetsYourControl=Exilia {0} que controles
|
|
||||||
lblExileNCardFromSameZone=Exilia la carta {0} del mismo {1}
|
|
||||||
lblExileNCardFromYourZone=Exilia la carta {0} de tu {1}
|
|
||||||
lblExileNTargetFromSameZone=Exilia {0} del mismo {1}
|
|
||||||
#ReplacementHandler.java
|
#ReplacementHandler.java
|
||||||
lblChooseFirstApplyReplacementEffect=Elige un efecto de reemplazo para aplicar primero.
|
lblChooseFirstApplyReplacementEffect=Elige un efecto de reemplazo para aplicar primero.
|
||||||
lblApplyCardReplacementEffectToCardConfirm=¿Aplicar efecto de reemplazo de {0} a {1}?\r\n{2}
|
lblApplyCardReplacementEffectToCardConfirm=¿Aplicar efecto de reemplazo de {0} a {1}?\r\n{2}
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@ lblOtherFormats=Other Formats...
|
|||||||
lblChooseSets=Choose Sets...
|
lblChooseSets=Choose Sets...
|
||||||
#HistoricFormatSelect.java
|
#HistoricFormatSelect.java
|
||||||
lblChooseFormat=Choose Format
|
lblChooseFormat=Choose Format
|
||||||
|
#Card.java
|
||||||
|
lblAdventure=Adventure
|
||||||
#TriggerAdapt.java
|
#TriggerAdapt.java
|
||||||
lblAdapt=Adapt
|
lblAdapt=Adapt
|
||||||
#TriggerAttached.java
|
#TriggerAttached.java
|
||||||
@@ -2286,14 +2288,6 @@ lblCostPaymentInvalid=Cost payment invalid
|
|||||||
lblSelectATargetToTap=Select a {0} to tap ({1} left)
|
lblSelectATargetToTap=Select a {0} to tap ({1} left)
|
||||||
lblSelectATargetToUntap=Select a {0} to untap ({1} left)
|
lblSelectATargetToUntap=Select a {0} to untap ({1} left)
|
||||||
lblUnattachCardConfirm=Unattach {0}?
|
lblUnattachCardConfirm=Unattach {0}?
|
||||||
#CostExile.java
|
|
||||||
lblExileTargetsFromYourZone=Exile {0} from your {1}
|
|
||||||
lblExileTarget=Exile {0}
|
|
||||||
lblExileAllCardsFromYourZone=Exile all cards from your {0}
|
|
||||||
lblExileTargetsYourControl=Exile {0} you control
|
|
||||||
lblExileNCardFromSameZone=Exile card {0} from the same {1}
|
|
||||||
lblExileNCardFromYourZone=Exile card {0} from your {1}
|
|
||||||
lblExileNTargetFromSameZone=Exile {0} from the same {1}
|
|
||||||
#ReplacementHandler.java
|
#ReplacementHandler.java
|
||||||
lblChooseFirstApplyReplacementEffect=Choose a replacement effect to apply first.
|
lblChooseFirstApplyReplacementEffect=Choose a replacement effect to apply first.
|
||||||
lblApplyCardReplacementEffectToCardConfirm=Apply replacement effect of {0} to {1}?\r\n{2}
|
lblApplyCardReplacementEffectToCardConfirm=Apply replacement effect of {0} to {1}?\r\n{2}
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@ lblOtherFormats=他のフォーマット...
|
|||||||
lblChooseSets=セットを選択
|
lblChooseSets=セットを選択
|
||||||
#HistoricFormatSelect.java
|
#HistoricFormatSelect.java
|
||||||
lblChooseFormat=フォーマットを選択
|
lblChooseFormat=フォーマットを選択
|
||||||
|
#Card.java
|
||||||
|
lblAdventure=出来事
|
||||||
#TriggerAdapt.java
|
#TriggerAdapt.java
|
||||||
lblAdapt=順応
|
lblAdapt=順応
|
||||||
#TriggerAttached.java
|
#TriggerAttached.java
|
||||||
@@ -2285,14 +2287,6 @@ lblCostPaymentInvalid=無効な支払い
|
|||||||
lblSelectATargetToTap=タップする {0}を選択(残り{1})
|
lblSelectATargetToTap=タップする {0}を選択(残り{1})
|
||||||
lblSelectATargetToUntap=アンタップする {0}を選択(残り{1})
|
lblSelectATargetToUntap=アンタップする {0}を選択(残り{1})
|
||||||
lblUnattachCardConfirm={0}を外しますか?
|
lblUnattachCardConfirm={0}を外しますか?
|
||||||
#CostExile.java
|
|
||||||
lblExileTargetsFromYourZone=あなたの {1}から {0}を追放
|
|
||||||
lblExileTarget={0}を追放
|
|
||||||
lblExileAllCardsFromYourZone=あなたの {0}からすべてのカードを追放
|
|
||||||
lblExileTargetsYourControl=あなたがコントロールする {0}を追放
|
|
||||||
lblExileNCardFromSameZone=同じ {1}から {0}カードを追放
|
|
||||||
lblExileNCardFromYourZone=あなたの {1}から {0}カードを追放
|
|
||||||
lblExileNTargetFromSameZone=同じ {1}から {0}を追放
|
|
||||||
#ReplacementHandler.java
|
#ReplacementHandler.java
|
||||||
lblChooseFirstApplyReplacementEffect=最初に適用する置換効果を選択してください。
|
lblChooseFirstApplyReplacementEffect=最初に適用する置換効果を選択してください。
|
||||||
lblApplyCardReplacementEffectToCardConfirm={0}の置換効果を{1}に適用しますか?\r\n{2}
|
lblApplyCardReplacementEffectToCardConfirm={0}の置換効果を{1}に適用しますか?\r\n{2}
|
||||||
|
|||||||
@@ -1415,6 +1415,8 @@ lblOtherFormats=其他赛制
|
|||||||
lblChooseSets=选择系列
|
lblChooseSets=选择系列
|
||||||
#HistoricFormatSelect.java
|
#HistoricFormatSelect.java
|
||||||
lblChooseFormat=选择赛制
|
lblChooseFormat=选择赛制
|
||||||
|
#Card.java
|
||||||
|
lblAdventure=Adventure
|
||||||
#TriggerAdapt.java
|
#TriggerAdapt.java
|
||||||
lblAdapt=演化
|
lblAdapt=演化
|
||||||
#TriggerAttached.java
|
#TriggerAttached.java
|
||||||
@@ -2283,14 +2285,6 @@ lblCostPaymentInvalid=付费失败
|
|||||||
lblSelectATargetToTap=选择{0}进行横置(还剩{1})
|
lblSelectATargetToTap=选择{0}进行横置(还剩{1})
|
||||||
lblSelectATargetToUntap=选择{0}进行重置(还剩{1})
|
lblSelectATargetToUntap=选择{0}进行重置(还剩{1})
|
||||||
lblUnattachCardConfirm=取消结附{0}?
|
lblUnattachCardConfirm=取消结附{0}?
|
||||||
#CostExile.java
|
|
||||||
lblExileTargetsFromYourZone=从你的{1}放逐{0}
|
|
||||||
lblExileTarget=放逐{0}
|
|
||||||
lblExileAllCardsFromYourZone=从你的{0}中放逐所有牌
|
|
||||||
lblExileTargetsYourControl=放逐你操控的{0}
|
|
||||||
lblExileNCardFromSameZone=从同一{1}中的卡牌中放逐{0}张牌
|
|
||||||
lblExileNCardFromYourZone=从你的{1}中放逐{0}张牌
|
|
||||||
lblExileNTargetFromSameZone=从同一{1}中的卡牌中放逐{0}
|
|
||||||
#ReplacementHandler.java
|
#ReplacementHandler.java
|
||||||
lblChooseFirstApplyReplacementEffect=选择首先生效的替代性效应。
|
lblChooseFirstApplyReplacementEffect=选择首先生效的替代性效应。
|
||||||
lblApplyCardReplacementEffectToCardConfirm=对{1}应用替代性效应{0}?\r\n{2}
|
lblApplyCardReplacementEffectToCardConfirm=对{1}应用替代性效应{0}?\r\n{2}
|
||||||
|
|||||||
Reference in New Issue
Block a user