From 51c9cc5b2ca1c2fc7c2973ba3aa8a7af24106299 Mon Sep 17 00:00:00 2001 From: Ferywir <65760459+Ferywir@users.noreply.github.com> Date: Wed, 17 Jun 2026 15:24:37 +0200 Subject: [PATCH] i18n: render battle reports in each reader's language (EN/FR/RO) (#236) --- GameEngine/Automation.php | 136 +++++++++++++++++++------------------- GameEngine/Database.php | 4 +- GameEngine/Lang/en.php | 105 +++++++++++++++++++++++++++++ GameEngine/Lang/fr.php | 59 +++++++++++++++++ GameEngine/Lang/ro.php | 59 +++++++++++++++++ Templates/Notice/1.tpl | 6 +- Templates/Notice/10.tpl | 2 +- Templates/Notice/15.tpl | 6 +- Templates/Notice/22.tpl | 6 +- Templates/Notice/3.tpl | 6 +- Templates/Notice/8.tpl | 6 +- 11 files changed, 309 insertions(+), 86 deletions(-) diff --git a/GameEngine/Automation.php b/GameEngine/Automation.php index 52aa81e5..aa0c2a22 100644 --- a/GameEngine/Automation.php +++ b/GameEngine/Automation.php @@ -131,7 +131,7 @@ class Automation { public function procResType($ref, $mode = 0) { //Capital or only 1 village left = cannot be destroyed - return addslashes(empty($build = Building::procResType($ref)) && !$mode ? "Village can't be" : $build); + return addslashes(empty($build = Building::procResType($ref)) && !$mode ? RC_VILLAGE_CANT_BE : $build); } function recountPop($vid, $use_cache = true){ @@ -794,8 +794,8 @@ class Automation { if ($isSecondRow) { if ($tbid > 0) { - $info_cat .= "Information - \"Catapult\" ".$this->procResType($tbgid, $can_destroy)." destroyed."; + $info_cat .= "".INFORMATION." + \"".rc_tok('RC_CATAPULT')."\" ".rc_bld($tbgid, $can_destroy)." ".rc_tok('RC_DESTROYED')."."; } // embassy level was changed @@ -805,7 +805,7 @@ class Automation { $info_cat .= ""; } else { - $info_cat = "".$catp_pic.", ".$this->procResType($tbgid, $can_destroy)." destroyed."; + $info_cat = "".$catp_pic.", ".rc_bld($tbgid, $can_destroy)." ".rc_tok('RC_DESTROYED')."."; // embassy level was changed if ($tbgid == 18){ @@ -817,11 +817,11 @@ class Automation { elseif($newLevel == $tblevel){ if($isSecondRow) { if ($tbid > 0) { - $info_cat .= "Information - \"Catapult\" ".$this->procResType($tbgid, $can_destroy)." was not damaged."; + $info_cat .= "".INFORMATION." + \"".rc_tok('RC_CATAPULT')."\" ".rc_bld($tbgid, $can_destroy)." ".rc_tok('RC_NOT_DAMAGED').""; } } else { - $info_cat = "".$catp_pic.",".$this->procResType($tbgid, $can_destroy)." was not damaged."; + $info_cat = "".$catp_pic.",".rc_bld($tbgid, $can_destroy)." ".rc_tok('RC_NOT_DAMAGED'); } } // building/field was damaged, let's calculate the actual damage @@ -831,7 +831,7 @@ class Automation { $bdo['f'.$catapultTarget] = $newLevel; // building was damaged to a lower level - $info_cata = " damaged from level ".$tblevel." to level ".$newLevel."."; + $info_cata = " ".rc_tok('RC_DAMAGED_FROM_TO', $tblevel, $newLevel); $buildarray = $GLOBALS["bid".$tbgid]; @@ -857,8 +857,8 @@ class Automation { } if ($isSecondRow) { - $info_cat .= "Information - \"Catapult\" ".$this->procResType($tbgid, $can_destroy).$info_cata; + $info_cat .= "".INFORMATION." + \"".rc_tok('RC_CATAPULT')."\" ".rc_bld($tbgid, $can_destroy).$info_cata; // embassy level was changed if ($tbgid == 18) { @@ -867,7 +867,7 @@ class Automation { $info_cat .= ""; } else { - $info_cat = "" . $catp_pic . "," . $this->procResType($tbgid, $can_destroy).$info_cata; + $info_cat = "" . $catp_pic . "," . rc_bld($tbgid, $can_destroy).$info_cata; // embassy level was changed if ($tbgid == 18) { @@ -877,10 +877,10 @@ class Automation { } }else{ if(!isset($info_cat) || empty($info_cat) || $info_cat == ","){ - $info_cat = "".$catp_pic.", There are no buildings left to destroy"; - }else if(strpos($info_cat, "There are no buildings left") === false){ - $info_cat .= "Information - \"Catapult\" There are no buildings left to destroy."; + $info_cat = "".$catp_pic.", ".rc_tok('RC_NO_BUILDINGS'); + }else if(strpos($info_cat, rc_tok('RC_NO_BUILDINGS')) === false){ + $info_cat .= "".INFORMATION." + \"".rc_tok('RC_CATAPULT')."\" ".rc_tok('RC_NO_BUILDINGS')."."; } } } @@ -897,8 +897,8 @@ class Automation { // village has been destroyed if ($pop <= 0) { - if ($can_destroy == 1) $info_cat = "".$catp_pic.", Village already destroyed."; - else $info_cat = "".$catp_pic.", Village can\'t be destroyed."; + if ($can_destroy == 1) $info_cat = "".$catp_pic.", ".rc_tok('RC_VILLAGE_ALREADY_DESTROYED'); + else $info_cat = "".$catp_pic.", ".rc_tok('RC_VILLAGE_CANT_DESTROY'); } else { @@ -1163,7 +1163,7 @@ class Automation { } if ($type != 3) { - $info_chief = $chief_pic . ',Could not reduce cultural points during raid'; + $info_chief = $chief_pic . ',' . rc_tok('RC_NO_REDUCE_CP_RAID'); return ['info_chief' => $info_chief, 'chiefing_village' => $chiefing_village, 'village_destroyed' => $village_destroyed]; } @@ -1197,22 +1197,22 @@ class Automation { $user_cps = $database->getUserArray($from['owner'], 1)['cp']; if ($user_cps < $need_cps) { - $info_chief = $chief_pic . ',Not enough culture points.'; + $info_chief = $chief_pic . ',' . rc_tok('RC_NOT_ENOUGH_CP'); return ['info_chief' => $info_chief, 'chiefing_village' => $chiefing_village, 'village_destroyed' => $village_destroyed]; } if (count($varray) <= 1 || $to['capital'] == 1 || $villexp >= $canconquer) { - $info_chief = $chief_pic . ',You cant take over this village.'; + $info_chief = $chief_pic . ',' . rc_tok('RC_CANT_TAKEOVER'); return ['info_chief' => $info_chief, 'chiefing_village' => $chiefing_village, 'village_destroyed' => $village_destroyed]; } if ($to['owner'] == 3 && $to['name'] == 'WW Buildingplan') { - $info_chief = $chief_pic . ',You cant take over this village.'; + $info_chief = $chief_pic . ',' . rc_tok('RC_CANT_TAKEOVER'); return ['info_chief' => $info_chief, 'chiefing_village' => $chiefing_village, 'village_destroyed' => $village_destroyed]; } if ($database->getFieldLevelInVillage($data['to'], '25, 26')) { - $info_chief = $chief_pic . ',The Palace/Residence isn\'t destroyed!'; + $info_chief = $chief_pic . ',' . rc_tok('RC_RESIDENCE_NOT_DESTROYED'); return ['info_chief' => $info_chief, 'chiefing_village' => $chiefing_village, 'village_destroyed' => $village_destroyed]; } @@ -1234,7 +1234,7 @@ class Automation { } if (($toF['loyalty'] - $reducedLoyaltyTotal) > 0) { - $info_chief = $chief_pic . ',The loyalty was lowered from ' . floor($toF['loyalty']) . ' to ' . floor($toF['loyalty'] - $reducedLoyaltyTotal) . '.'; + $info_chief = $chief_pic . ',' . rc_tok('RC_LOYALTY_LOWERED', floor($toF['loyalty']), floor($toF['loyalty'] - $reducedLoyaltyTotal)); $database->setVillageField($data['to'], 'loyalty', ($toF['loyalty'] - $reducedLoyaltyTotal)); return ['info_chief' => $info_chief, 'chiefing_village' => $chiefing_village, 'village_destroyed' => $village_destroyed]; } @@ -1247,7 +1247,7 @@ class Automation { $villname = addslashes($database->getVillageField($data['to'], 'name')); $artifact = reset($database->getOwnArtefactInfo($data['to'])); - $info_chief = $chief_pic . ',Inhabitants of ' . $villname . ' village decided to join your empire.'; + $info_chief = $chief_pic . ',' . rc_tok('RC_INHABITANTS_JOIN', $villname); if ($artifact['vref'] == $data['to']) { $database->claimArtefact($data['to'], $data['to'], $database->getVillageField($data['from'], 'owner')); @@ -1394,29 +1394,29 @@ class Automation { global $database; $info_spy = ""; if ($data['spy'] == 1){ - $info_spy = "".$spy_pic.",
\"Lumber\"".round($totwood)." | - \"Clay\"".round($totclay)." | - \"Iron\"".round($totiron)." | - \"Crop\"".round($totcrop)."
-
\"carry\"Total Resources: ".round($totwood+$totclay+$totiron+$totcrop)."
+ $info_spy = "".$spy_pic.",
\"".LUMBER."\"".round($totwood)." | + \"".CLAY."\"".round($totclay)." | + \"".IRON."\"".round($totiron)." | + \"".CROP."\"".round($totcrop)."
+
\"".rc_tok('CARRY')."\"".rc_tok('RC_TOTAL_RESOURCES')." ".round($totwood+$totclay+$totiron+$totcrop)."
"; }else if($data['spy'] == 2){ if ($isoasis == 0){ $walllevel = $database->getFieldLevelInVillage($data['to'], '31, 32, 33'); $residencelevel = $database->getFieldLevelInVillage($data['to'], 25); $palacelevel = $database->getFieldLevelInVillage($data['to'], 26); - $residenceimg = "\"Residence\""; - $palaceimg = "\"Palace\""; - $crannyimg = "\"Cranny\""; - $wallimg = "\"Wall\""; + $residenceimg = "\"".RESIDENCE."\""; + $palaceimg = "\"".PALACE."\""; + $crannyimg = "\"".CRANNY."\""; + $wallimg = "\"".rc_tok('RC_WALL')."\""; $info_spy = "".$spy_pic.","; - if($residencelevel > 0) $info_spy .= $residenceimg." Residence level:".$residencelevel."
"; - elseif($palacelevel > 0) $info_spy .= $palaceimg." Palace level: ".$palacelevel."
"; - - if($walllevel > 0) $info_spy .= $wallimg." Wall level: ".$walllevel."
"; - $info_spy .= $crannyimg." Total crannies capacity: ".$crannySpy.""; + if($residencelevel > 0) $info_spy .= $residenceimg." ".rc_tok('RC_RESIDENCE_LEVEL')."".$residencelevel."
"; + elseif($palacelevel > 0) $info_spy .= $palaceimg." ".rc_tok('RC_PALACE_LEVEL')." ".$palacelevel."
"; + + if($walllevel > 0) $info_spy .= $wallimg." ".rc_tok('RC_WALL_LEVEL')." ".$walllevel."
"; + $info_spy .= $crannyimg." ".rc_tok('RC_CRANNY_CAPACITY')." ".$crannySpy.""; } - else $info_spy = "".$spy_pic.", There are no informations to show"; + else $info_spy = "".$spy_pic.", ".rc_tok('RC_NO_INFO'); } return $info_spy; } @@ -1520,8 +1520,8 @@ class Automation { } $database->deletePrisoners($prisoners2delete); - $ownDeadsText = ($ownAlive = $mytroops - $ownDeads) > 0 ? " of which ".$ownAlive." have been saved" : ""; - $anotherDeadsText = ($anotherAlive = $anothertroops - $anotherDeads) > 0 ? " of which ".$anotherAlive." have been saved" : ""; + $ownDeadsText = ($ownAlive = $mytroops - $ownDeads) > 0 ? " ".rc_tok('RC_OF_WHICH_SAVED',$ownAlive) : ""; + $anotherDeadsText = ($anotherAlive = $anothertroops - $anotherDeads) > 0 ? " ".rc_tok('RC_OF_WHICH_SAVED',$anotherAlive) : ""; $database->addGeneralAttack($ownDeads + $anotherDeads); @@ -1535,15 +1535,15 @@ class Automation { $database->trainUnit($to['wref'], 99, $newtraps, $u99['pop'], $repairDuration, 0); } - $trapper_pic = "\"Trap\""; + $trapper_pic = "\"".rc_tok('RC_TRAP')."\""; $p_username = $database->getUserField($from['owner'], "username", 0); if ($mytroops > 0 && $anothertroops > 0) { - return $trapper_pic." ".$p_username." freed ".$mytroops." from his troops".$ownDeadsText." and ".$anothertroops." friendly troops".$anotherDeadsText."."; + return $trapper_pic." ".$p_username." ".rc_tok('RC_FREED_FROM_HIS_TROOPS', $mytroops).$ownDeadsText." ".rc_tok('RC_AND_FRIENDLY_TROOPS', $anothertroops).$anotherDeadsText."."; } elseif ($mytroops > 0) { - return $trapper_pic." ".$p_username." freed ".$mytroops." from his troops".$ownDeadsText."."; + return $trapper_pic." ".$p_username." ".rc_tok('RC_FREED_FROM_HIS_TROOPS', $mytroops).$ownDeadsText."."; } elseif ($anothertroops > 0) { - return $trapper_pic." ".$p_username." freed ".$anothertroops." friendly troops".$anotherDeadsText."."; + return $trapper_pic." ".$p_username." ".rc_tok('RC_FREED_FRIENDLY_TROOPS', $anothertroops).$anotherDeadsText."."; } return ''; } @@ -1613,10 +1613,10 @@ class Automation { .',,'.$unitstraped_att; } else { if (isset($village_destroyed) && $village_destroyed == 1 && $can_destroy == 1) { - if (strpos($info_cat, "The village has") === false) { - $info_cat .= "Information" - . "\"Catapult\"" - . " The village has been destroyed."; + if (strpos($info_cat, rc_tok('RC_VILLAGE_DESTROYED')) === false) { + $info_cat .= "".INFORMATION."" + . "\"".rc_tok('RC_CATAPULT')."\"" + . " ".rc_tok('RC_VILLAGE_DESTROYED').""; } } $data2 = ''.$from['owner'].','.$from['wref'].','.$owntribe.','.$unitssend_att.','.$unitsdead_att @@ -2114,7 +2114,7 @@ class Automation { private function applyRamDamage($data, $walllevel, $wallid, $ram_pic, $battlepart, array $ctx) { global $database, $battle; - $info_ram = "".$ram_pic.",There is no wall to destroy."; + $info_ram = "".$ram_pic.",".rc_tok('RC_NO_WALL'); if($walllevel > 0){ $ramsDamage = $battle->calculateCatapultsDamage($data['t7'], @@ -2126,13 +2126,13 @@ class Automation { $newLevel = $battle->calculateNewBuildingLevel($walllevel, $ramsDamage); if ($newLevel == 0){ - $info_ram = "".$ram_pic.",Wall destroyed."; + $info_ram = "".$ram_pic.",".rc_tok('RC_WALL_DESTROYED'); $database->setVillageLevel($data['to'], ["f".$wallid, "f".$wallid."t"], [0, 0]); $this->recountPop($data['to']); }elseif ($newLevel == $walllevel){ - $info_ram = "".$ram_pic.",Wall was not damaged."; + $info_ram = "".$ram_pic.",".rc_tok('RC_WALL_NOT_DAMAGED'); }else{ - $info_ram = "".$ram_pic.",Wall damaged from level ".$walllevel." to level ".$newLevel."."; + $info_ram = "".$ram_pic.",".rc_tok('RC_WALL_DAMAGED_FROM_TO', $walllevel, $newLevel); $database->setVillageLevel($data['to'],"f".$wallid."",$newLevel); } @@ -2650,10 +2650,10 @@ class Automation { if(($data['t11'] - $dead11 - $traped11) > 0){ //hero if ($heroxp == 0) { $xp = ""; - $info_hero = $hero_pic.",Your hero had nothing to kill therefore gains no XP at all."; + $info_hero = $hero_pic.",".rc_tok('RC_HERO_NO_KILL'); } else { - $xp = " and gained ".$heroxp." XP from the battle."; - $info_hero = $hero_pic.",Your hero gained ".$heroxp." XP."; + $xp = " ".rc_tok('RC_HERO_AND_GAINED_XP_BATTLE', $heroxp); + $info_hero = $hero_pic.",".rc_tok('RC_HERO_GAINED_XP', $heroxp); } if ($isoasis != 0) { //oasis fix by ronix @@ -2662,7 +2662,7 @@ class Automation { $canqured = $database->canConquerOasis($data['from'], $data['to'], false); if ($canqured == 1 && $troopcount == 0) { $database->conquerOasis($data['from'], $data['to']); - $info_hero = $hero_pic.",Your hero has conquered this oasis".$xp; + $info_hero = $hero_pic.",".rc_tok('RC_HERO_CONQUERED_OASIS').$xp; }else{ if ($canqured == 3 && $troopcount == 0) { if ($type == 3) { @@ -2670,40 +2670,40 @@ class Automation { //$database->modifyOasisLoyalty($data['to']); //$OasisInfo = $database->getOasisInfo($data['to']); $Oloyaltynow = intval($database->modifyOasisLoyalty($data['to']));//intval($OasisInfo['loyalty']); - $info_hero = $hero_pic.",Your hero has reduced oasis loyalty to ".$Oloyaltynow." from ".$Oloyaltybefore.$xp; + $info_hero = $hero_pic.",".rc_tok('RC_HERO_REDUCED_OASIS_LOYALTY', $Oloyaltynow, $Oloyaltybefore).$xp; } - else $info_hero = $hero_pic.",Could not reduce loyalty during raid".$xp; + else $info_hero = $hero_pic.",".rc_tok('RC_NO_REDUCE_LOYALTY_RAID').$xp; } } } } else { - if ($heroxp == 0) $xp=" no XP from the battle."; - else $xp=" gained ".$heroxp." XP from the battle."; + if ($heroxp == 0) $xp=" ".rc_tok('RC_HERO_NO_XP_BATTLE'); + else $xp=" ".rc_tok('RC_HERO_GAINED_XP_BATTLE', $heroxp); $artifact = reset($database->getOwnArtefactInfo($data['to'])); if (!empty($artifact)) { if ($type == 3) { if (empty($artifactError = $database->canClaimArtifact($data['from'], $artifact['vref'], $artifact['size'], $artifact['type']))) { $database->claimArtefact($data['from'], $data['to'], $database->getVillageField($data['from'], "owner")); - $info_hero = $hero_pic.",Your hero is carrying home the artifact ".$artifact['name']." and".$xp; + $info_hero = $hero_pic.",".rc_tok('RC_HERO_CARRYING_ARTIFACT', $artifact['name']).$xp; // if the defender pop is 0 with no artefact, then destroy the village if($database->getVillageField($data['to'], "pop") == 0 || $targettribe == 5){ $can_destroy = $village_destroyed = 1; - if(strpos($info_cat, "The village has") === false) $info_hero .= " The village has been destroyed."; + if(strpos($info_cat, rc_tok('RC_VILLAGE_DESTROYED')) === false) $info_hero .= " ".rc_tok('RC_VILLAGE_DESTROYED'); } } else $info_hero = $hero_pic.",".$artifactError.$xp; } - else $info_hero = $hero_pic.",Your hero could not claim an artifact during raid".$xp; + else $info_hero = $hero_pic.",".rc_tok('RC_HERO_NO_ARTIFACT_RAID').$xp; } } }elseif($data['t11'] > 0) { if ($heroxp == 0) $xp = ""; - else $xp = " but gained ".$heroxp." XP from the battle."; + else $xp = " ".rc_tok('RC_HERO_BUT_GAINED_XP_BATTLE', $heroxp); - if ($traped11 > 0) $info_hero = $hero_pic.",Your hero was trapped".$xp; - else $info_hero = $hero_pic.",Your hero died".$xp; + if ($traped11 > 0) $info_hero = $hero_pic.",".rc_tok('RC_HERO_TRAPPED').$xp; + else $info_hero = $hero_pic.",".rc_tok('RC_HERO_DIED').$xp; } } @@ -3289,7 +3289,7 @@ class Automation { // prisoners freed during conquest attacks — extracted to handlePrisoners() [#155] $info_trap = empty($scout) ? $this->handlePrisoners($data, $from, $to, $ownally, $type, $totalsend_att, $totaldead_att, $totaltraped_att) : ''; - $info_troop = ($totalsend_att - ($totaldead_att + (isset($totaltraped_att) ? $totaltraped_att : 0)) <= 0) ? "None of your soldiers returned." : ""; + $info_troop = ($totalsend_att - ($totaldead_att + (isset($totaltraped_att) ? $totaltraped_att : 0)) <= 0) ? rc_tok('RC_NONE_RETURNED') : ""; // assemble data2 + data_fail — extracted to buildCombatReport() [#155] $report = $this->buildCombatReport( diff --git a/GameEngine/Database.php b/GameEngine/Database.php index 9a300206..52484110 100755 --- a/GameEngine/Database.php +++ b/GameEngine/Database.php @@ -5187,8 +5187,8 @@ $q = "INSERT INTO ".TB_PREFIX."demolition VALUES ( 'lvl' => $current_level ], false, $use_cache); - if ($allianceStatus === false) return ' This player\'s alliance has been dispersed.'; - else if ($allianceStatus === 0) return ' Player was forced to leave their alliance.'; + if ($allianceStatus === false) return ' ' . rc_tok('MSG_ALLIANCE_DISPERSED_STATUS'); + else if ($allianceStatus === 0) return ' ' . rc_tok('MSG_FORCED_LEAVE_STATUS'); else return ''; // all is good, no need to append additional alliance-related text } diff --git a/GameEngine/Lang/en.php b/GameEngine/Lang/en.php index 24a92d1f..c1bb52c0 100755 --- a/GameEngine/Lang/en.php +++ b/GameEngine/Lang/en.php @@ -200,6 +200,65 @@ tz_def('NATAR_COUNTERFORCE', 'Natar Counterforce'); tz_def('FROM_THE_VILL', 'from the village'); tz_def('CASUALTIES', 'Casualties'); tz_def('INFORMATION', 'Information'); +// === Battle report strings (issue: i18n of combat reports) === +tz_def('RC_HERO', 'Hero'); +tz_def('RC_CATAPULT', 'Catapult'); +tz_def('RC_TRAP', 'Trap'); +tz_def('RC_WALL', 'Wall'); +tz_def('TZ_AT', 'at'); +// Catapults +tz_def('RC_DESTROYED', 'destroyed'); +tz_def('RC_NOT_DAMAGED', 'was not damaged.'); +tz_def('RC_DAMAGED_FROM_TO', 'damaged from level %s to level %s.'); +tz_def('RC_NO_BUILDINGS', 'There are no buildings left to destroy'); +tz_def('RC_VILLAGE_ALREADY_DESTROYED', 'Village already destroyed.'); +tz_def('RC_VILLAGE_CANT_DESTROY', "Village can't be destroyed."); +tz_def('RC_VILLAGE_CANT_BE', "Village can't be"); +tz_def('RC_VILLAGE_DESTROYED', 'The village has been destroyed.'); +// Rams +tz_def('RC_NO_WALL', 'There is no wall to destroy.'); +tz_def('RC_WALL_DESTROYED', 'Wall destroyed.'); +tz_def('RC_WALL_NOT_DAMAGED', 'Wall was not damaged.'); +tz_def('RC_WALL_DAMAGED_FROM_TO', 'Wall damaged from level %s to level %s.'); +// Conquest / chief +tz_def('RC_NO_REDUCE_CP_RAID', 'Could not reduce cultural points during raid'); +tz_def('RC_NOT_ENOUGH_CP', 'Not enough culture points.'); +tz_def('RC_CANT_TAKEOVER', 'You cant take over this village.'); +tz_def('RC_RESIDENCE_NOT_DESTROYED', "The Palace/Residence isn't destroyed!"); +tz_def('RC_LOYALTY_LOWERED', 'The loyalty was lowered from %s to %s.'); +tz_def('RC_INHABITANTS_JOIN', 'Inhabitants of %s village decided to join your empire.'); +// Hero +tz_def('RC_HERO_NO_KILL', 'Your hero had nothing to kill therefore gains no XP at all.'); +tz_def('RC_HERO_GAINED_XP', 'Your hero gained %s XP.'); +tz_def('RC_HERO_CONQUERED_OASIS', 'Your hero has conquered this oasis'); +tz_def('RC_HERO_REDUCED_OASIS_LOYALTY', 'Your hero has reduced oasis loyalty to %s from %s'); +tz_def('RC_NO_REDUCE_LOYALTY_RAID', 'Could not reduce loyalty during raid'); +tz_def('RC_HERO_CARRYING_ARTIFACT', 'Your hero is carrying home the artifact %s and'); +tz_def('RC_HERO_NO_ARTIFACT_RAID', 'Your hero could not claim an artifact during raid'); +tz_def('RC_HERO_AND_GAINED_XP_BATTLE', 'and gained %s XP from the battle.'); +tz_def('RC_HERO_NO_XP_BATTLE', 'no XP from the battle.'); +tz_def('RC_HERO_GAINED_XP_BATTLE', 'gained %s XP from the battle.'); +tz_def('RC_HERO_BUT_GAINED_XP_BATTLE', 'but gained %s XP from the battle.'); +tz_def('RC_HERO_TRAPPED', 'Your hero was trapped'); +tz_def('RC_HERO_DIED', 'Your hero died'); +// Scout report +tz_def('RC_TOTAL_RESOURCES', 'Total Resources:'); +tz_def('RC_RESIDENCE_LEVEL', 'Residence level:'); +tz_def('RC_PALACE_LEVEL', 'Palace level:'); +tz_def('RC_WALL_LEVEL', 'Wall level:'); +tz_def('RC_CRANNY_CAPACITY', 'Total crannies capacity:'); +tz_def('RC_NO_INFO', 'There are no informations to show'); +// Prisoners / traps +tz_def('RC_OF_WHICH_SAVED', 'of which %s have been saved'); +tz_def('RC_FREED_FROM_HIS_TROOPS', 'freed %s from his troops'); +tz_def('RC_FREED_FRIENDLY_TROOPS', 'freed %s friendly troops'); +tz_def('RC_AND_FRIENDLY_TROOPS', 'and %s friendly troops'); +// Troop return +tz_def('RC_NONE_RETURNED', 'None of your soldiers returned.'); +// === End battle report strings === +// Embassy-destruction status lines, appended to the catapult battle report. +tz_def('MSG_ALLIANCE_DISPERSED_STATUS', "This player's alliance has been dispersed."); +tz_def('MSG_FORCED_LEAVE_STATUS', 'Player was forced to leave their alliance.'); tz_def('CARRY', 'carry'); tz_def('DEFENDER', 'Defender'); tz_def('VISITED', 'visited'); @@ -2496,6 +2555,52 @@ tz_def('MANUAL_NF_D_24', "The medal of which is awarded to players losing by the tz_def('MANUAL_NF_D_25', "The medal of which is awarded to players losing by the same email address of 10 or more years. Can be added to the profile description. This function was presented in Travian T4."); tz_def('MANUAL_NF_D_26', "The medal of which is awarded to players losing by the same email address of 10 or more years. Can be added to the profile description. This function was presented in Travian T4."); +// ===== per-reader localization of battle reports (token layer) ===== +// Battle reports are generated server-side at resolution time, in whichever +// player's language happened to trigger the automation tick. To make the +// *body* read in each viewer's own language instead, the report builders store +// language-neutral TOKENS in the notice payload and tz_expand_report() expands +// them at display time in the reader's LANG. Token grammar (no commas, so it +// survives the CSV payload): +// {{KEY}} -> CONST (e.g. {{RC_WALL_NOT_DAMAGED}}) +// {{KEY|a|b}} -> vsprintf(CONST, [a, b]) (args are rawurlencoded) +// {{BLD|type|mode}} -> building name in the reader's language +// rc_tok()/rc_bld() are the emit-side helpers (used by the report builders). +// Unknown / undefined tokens are left untouched, and old reports stored as +// plain text (pre-token) pass through unchanged. +if (!function_exists('rc_tok')) { + function rc_tok($key /* , ...$args */) { + $args = array_slice(func_get_args(), 1); + if (!$args) return '{{' . $key . '}}'; + return '{{' . $key . '|' . implode('|', array_map('rawurlencode', $args)) . '}}'; + } +} +if (!function_exists('rc_bld')) { + function rc_bld($type, $mode = 0) { + return '{{BLD|' . (int) $type . '|' . (int) $mode . '}}'; + } +} +if (!function_exists('tz_build_name')) { + function tz_build_name($type, $mode = 0) { + $b = Building::procResType((int) $type); + return ($b === '' && !$mode) ? RC_VILLAGE_CANT_BE : $b; + } +} +if (!function_exists('tz_expand_report')) { + function tz_expand_report($s) { + if (!is_string($s) || strpos($s, '{{') === false) return $s; + return preg_replace_callback('/\{\{([A-Z0-9_]+)((?:\|[^|{}]*)*)\}\}/', function ($m) { + $key = $m[1]; + $args = ($m[2] === '') ? [] : array_map('rawurldecode', explode('|', substr($m[2], 1))); + if ($key === 'BLD') { + return tz_build_name($args[0] ?? 0, $args[1] ?? 0); + } + if (!defined($key)) return $m[0]; + return $args ? vsprintf(constant($key), $args) : constant($key); + }, $s); + } +} + // ===== display-time localization of stored report topics ===== // Reports are generated server-side at battle resolution and stored in the DB // (column `topic`) with English connectors. This rewrites them to the viewing diff --git a/GameEngine/Lang/fr.php b/GameEngine/Lang/fr.php index 82b528ce..cbfcfe72 100644 --- a/GameEngine/Lang/fr.php +++ b/GameEngine/Lang/fr.php @@ -197,6 +197,65 @@ define('NATAR_COUNTERFORCE', 'Contre-attaque Natar'); define('FROM_THE_VILL', 'du village'); define('CASUALTIES', 'Pertes'); define('INFORMATION', 'Information'); +// === Battle report strings (issue: i18n of combat reports) === +define('RC_HERO', 'Héros'); +define('RC_CATAPULT', 'Catapulte'); +define('RC_TRAP', 'Piège'); +define('RC_WALL', 'Muraille'); +define('TZ_AT', 'à'); +// Catapults +define('RC_DESTROYED', 'détruit'); +define('RC_NOT_DAMAGED', "n'a pas été endommagé."); +define('RC_DAMAGED_FROM_TO', 'endommagé du niveau %s au niveau %s.'); +define('RC_NO_BUILDINGS', 'Il ne reste aucun bâtiment à détruire'); +define('RC_VILLAGE_ALREADY_DESTROYED', 'Village déjà détruit.'); +define('RC_VILLAGE_CANT_DESTROY', 'Le village ne peut pas être détruit.'); +define('RC_VILLAGE_CANT_BE', 'Le village ne peut pas être'); +define('RC_VILLAGE_DESTROYED', 'Le village a été détruit.'); +// Rams +define('RC_NO_WALL', "Il n'y a pas de muraille à détruire."); +define('RC_WALL_DESTROYED', 'Muraille détruite.'); +define('RC_WALL_NOT_DAMAGED', "La muraille n'a pas été endommagée."); +define('RC_WALL_DAMAGED_FROM_TO', 'Muraille endommagée du niveau %s au niveau %s.'); +// Conquest / chief +define('RC_NO_REDUCE_CP_RAID', "Impossible de réduire les points de culture lors d'un raid"); +define('RC_NOT_ENOUGH_CP', 'Points de culture insuffisants.'); +define('RC_CANT_TAKEOVER', 'Vous ne pouvez pas conquérir ce village.'); +define('RC_RESIDENCE_NOT_DESTROYED', "Le Palais/la Résidence n'est pas détruit(e) !"); +define('RC_LOYALTY_LOWERED', 'La loyauté a été réduite de %s à %s.'); +define('RC_INHABITANTS_JOIN', 'Les habitants du village %s ont décidé de rejoindre votre empire.'); +// Hero +define('RC_HERO_NO_KILL', "Votre héros n'avait personne à tuer et ne gagne donc aucun XP."); +define('RC_HERO_GAINED_XP', 'Votre héros a gagné %s XP.'); +define('RC_HERO_CONQUERED_OASIS', 'Votre héros a conquis cette oasis'); +define('RC_HERO_REDUCED_OASIS_LOYALTY', "Votre héros a réduit la loyauté de l'oasis à %s depuis %s"); +define('RC_NO_REDUCE_LOYALTY_RAID', "Impossible de réduire la loyauté lors d'un raid"); +define('RC_HERO_CARRYING_ARTIFACT', "Votre héros rapporte l'artefact %s et"); +define('RC_HERO_NO_ARTIFACT_RAID', "Votre héros n'a pas pu s'emparer d'un artefact lors d'un raid"); +define('RC_HERO_AND_GAINED_XP_BATTLE', 'et a gagné %s XP lors de la bataille.'); +define('RC_HERO_NO_XP_BATTLE', 'aucun XP lors de la bataille.'); +define('RC_HERO_GAINED_XP_BATTLE', 'a gagné %s XP lors de la bataille.'); +define('RC_HERO_BUT_GAINED_XP_BATTLE', 'mais a gagné %s XP lors de la bataille.'); +define('RC_HERO_TRAPPED', 'Votre héros a été capturé'); +define('RC_HERO_DIED', 'Votre héros est mort'); +// Scout report +define('RC_TOTAL_RESOURCES', 'Ressources totales :'); +define('RC_RESIDENCE_LEVEL', 'Niveau de la Résidence :'); +define('RC_PALACE_LEVEL', 'Niveau du Palais :'); +define('RC_WALL_LEVEL', 'Niveau de la muraille :'); +define('RC_CRANNY_CAPACITY', 'Capacité totale des cachettes :'); +define('RC_NO_INFO', 'Aucune information à afficher'); +// Prisoners / traps +define('RC_OF_WHICH_SAVED', 'dont %s ont été sauvés'); +define('RC_FREED_FROM_HIS_TROOPS', 'a libéré %s de ses troupes'); +define('RC_FREED_FRIENDLY_TROOPS', 'a libéré %s troupes alliées'); +define('RC_AND_FRIENDLY_TROOPS', 'et %s troupes alliées'); +// Troop return +define('RC_NONE_RETURNED', "Aucun de vos soldats n'est revenu."); +// === End battle report strings === +// Embassy-destruction status lines, appended to the catapult battle report. +define('MSG_ALLIANCE_DISPERSED_STATUS', "L'alliance de ce joueur a été dispersée."); +define('MSG_FORCED_LEAVE_STATUS', "Le joueur a été forcé de quitter son alliance."); define('CARRY', 'transporte'); define('DEFENDER', 'Défenseur'); define('VISITED', 'visité'); diff --git a/GameEngine/Lang/ro.php b/GameEngine/Lang/ro.php index 99e85ae9..f98326e3 100644 --- a/GameEngine/Lang/ro.php +++ b/GameEngine/Lang/ro.php @@ -197,6 +197,65 @@ define('NATAR_COUNTERFORCE', 'Contraatac Natari'); define('FROM_THE_VILL', 'din satul'); define('CASUALTIES', 'Pierderi'); define('INFORMATION', 'Informații'); +// === Battle report strings (issue: i18n of combat reports) === +define('RC_HERO', 'Erou'); +define('RC_CATAPULT', 'Catapultă'); +define('RC_TRAP', 'Capcană'); +define('RC_WALL', 'Zid'); +define('TZ_AT', 'la'); +// Catapults +define('RC_DESTROYED', 'distrus'); +define('RC_NOT_DAMAGED', 'nu a fost avariat.'); +define('RC_DAMAGED_FROM_TO', 'avariat de la nivelul %s la nivelul %s.'); +define('RC_NO_BUILDINGS', 'Nu mai sunt clădiri de distrus'); +define('RC_VILLAGE_ALREADY_DESTROYED', 'Sat deja distrus.'); +define('RC_VILLAGE_CANT_DESTROY', 'Satul nu poate fi distrus.'); +define('RC_VILLAGE_CANT_BE', 'Satul nu poate fi'); +define('RC_VILLAGE_DESTROYED', 'Satul a fost distrus.'); +// Rams +define('RC_NO_WALL', 'Nu există zid de distrus.'); +define('RC_WALL_DESTROYED', 'Zid distrus.'); +define('RC_WALL_NOT_DAMAGED', 'Zidul nu a fost avariat.'); +define('RC_WALL_DAMAGED_FROM_TO', 'Zid avariat de la nivelul %s la nivelul %s.'); +// Conquest / chief +define('RC_NO_REDUCE_CP_RAID', 'Nu s-au putut reduce punctele de cultură în timpul unui raid'); +define('RC_NOT_ENOUGH_CP', 'Puncte de cultură insuficiente.'); +define('RC_CANT_TAKEOVER', 'Nu poți cuceri acest sat.'); +define('RC_RESIDENCE_NOT_DESTROYED', 'Palatul/Reședința nu este distrus(ă)!'); +define('RC_LOYALTY_LOWERED', 'Loialitatea a fost redusă de la %s la %s.'); +define('RC_INHABITANTS_JOIN', 'Locuitorii satului %s au decis să se alăture imperiului tău.'); +// Hero +define('RC_HERO_NO_KILL', 'Eroul tău nu a avut pe cine ucide, deci nu câștigă niciun XP.'); +define('RC_HERO_GAINED_XP', 'Eroul tău a câștigat %s XP.'); +define('RC_HERO_CONQUERED_OASIS', 'Eroul tău a cucerit această oază'); +define('RC_HERO_REDUCED_OASIS_LOYALTY', 'Eroul tău a redus loialitatea oazei la %s de la %s'); +define('RC_NO_REDUCE_LOYALTY_RAID', 'Nu s-a putut reduce loialitatea în timpul unui raid'); +define('RC_HERO_CARRYING_ARTIFACT', 'Eroul tău aduce acasă artefactul %s și'); +define('RC_HERO_NO_ARTIFACT_RAID', 'Eroul tău nu a putut revendica un artefact în timpul unui raid'); +define('RC_HERO_AND_GAINED_XP_BATTLE', 'și a câștigat %s XP din luptă.'); +define('RC_HERO_NO_XP_BATTLE', 'niciun XP din luptă.'); +define('RC_HERO_GAINED_XP_BATTLE', 'a câștigat %s XP din luptă.'); +define('RC_HERO_BUT_GAINED_XP_BATTLE', 'dar a câștigat %s XP din luptă.'); +define('RC_HERO_TRAPPED', 'Eroul tău a fost capturat'); +define('RC_HERO_DIED', 'Eroul tău a murit'); +// Scout report +define('RC_TOTAL_RESOURCES', 'Resurse totale:'); +define('RC_RESIDENCE_LEVEL', 'Nivel Reședință:'); +define('RC_PALACE_LEVEL', 'Nivel Palat:'); +define('RC_WALL_LEVEL', 'Nivel zid:'); +define('RC_CRANNY_CAPACITY', 'Capacitate totală ascunzători:'); +define('RC_NO_INFO', 'Nu există informații de afișat'); +// Prisoners / traps +define('RC_OF_WHICH_SAVED', 'dintre care %s au fost salvați'); +define('RC_FREED_FROM_HIS_TROOPS', 'a eliberat %s din trupele sale'); +define('RC_FREED_FRIENDLY_TROOPS', 'a eliberat %s trupe aliate'); +define('RC_AND_FRIENDLY_TROOPS', 'și %s trupe aliate'); +// Troop return +define('RC_NONE_RETURNED', 'Niciunul dintre soldații tăi nu s-a întors.'); +// === End battle report strings === +// Embassy-destruction status lines, appended to the catapult battle report. +define('MSG_ALLIANCE_DISPERSED_STATUS', 'Alianța acestui jucător a fost dispersată.'); +define('MSG_FORCED_LEAVE_STATUS', 'Jucătorul a fost forțat să-și părăsească alianța.'); define('CARRY', 'transportă'); define('DEFENDER', 'Apărător'); define('VISITED', 'vizitat'); diff --git a/Templates/Notice/1.tpl b/Templates/Notice/1.tpl index ac944a2d..555de5fb 100644 --- a/Templates/Notice/1.tpl +++ b/Templates/Notice/1.tpl @@ -7,7 +7,7 @@ # - No structural changes affecting gameplay ################################################################################# -$dataarray = explode(",", $message->readingNotice['data']); +$dataarray = array_map('tz_expand_report', explode(",", $message->readingNotice['data'])); // ======================== BASIC SETTINGS ======================== $hasHero = (isset($dataarray[178]) && $dataarray[178] > 0); @@ -80,7 +80,7 @@ if ($database->isVillageOases($dataarray[29])) { procMtime($message->readingNotice['time']); ?> - + @@ -113,7 +113,7 @@ for ($i = $start; $i <= ($start + 9); $i++) { } if ($hasHero) { - echo "\"Hero\""; + echo "\"".RC_HERO."\""; } echo "".TROOPS.""; diff --git a/Templates/Notice/10.tpl b/Templates/Notice/10.tpl index cb9b1064..82197a4a 100644 --- a/Templates/Notice/10.tpl +++ b/Templates/Notice/10.tpl @@ -7,7 +7,7 @@ # - Improved readability + minor performance gain ################################################################################# -$dataarray = explode(",", $message->readingNotice['data']); +$dataarray = array_map('tz_expand_report', explode(",", $message->readingNotice['data'])); // ======================== URL SETUP ======================== diff --git a/Templates/Notice/15.tpl b/Templates/Notice/15.tpl index 589fff33..b8c5bdf3 100644 --- a/Templates/Notice/15.tpl +++ b/Templates/Notice/15.tpl @@ -7,7 +7,7 @@ # - Minor safety fixes (undefined vars / repeated calls) ################################################################################# -$dataarray = explode(",", $message->readingNotice['data']); +$dataarray = array_map('tz_expand_report', explode(",", $message->readingNotice['data'])); // ======================== URL SETUP ======================== @@ -61,7 +61,7 @@ if ($fromName != "[?]") { procMtime($message->readingNotice['time']); ?> - + @@ -99,7 +99,7 @@ for ($i = $start; $i <= ($start + 9); $i++) { // hero column if ($hasHero) { - echo "\"Hero\""; + echo "\"".RC_HERO."\""; } echo "".TROOPS.""; diff --git a/Templates/Notice/22.tpl b/Templates/Notice/22.tpl index 29bc177d..142d1bc1 100644 --- a/Templates/Notice/22.tpl +++ b/Templates/Notice/22.tpl @@ -7,7 +7,7 @@ # - Safer handling for event type + arrays ################################################################################# -$dataarray = explode(",", $message->readingNotice['data']); +$dataarray = array_map('tz_expand_report', explode(",", $message->readingNotice['data'])); // ======================== CONFIG ======================== $hasHero = (!empty($dataarray[14]) && $dataarray[14] > 0); @@ -48,7 +48,7 @@ if ($type == 1) { procMtime($message->readingNotice['time']); ?> - + @@ -95,7 +95,7 @@ for ($i = $start; $i <= ($start + 9); $i++) { // HERO if ($hasHero) { - echo "\"Hero\""; + echo "\"".RC_HERO."\""; } echo "".TROOPS.""; diff --git a/Templates/Notice/3.tpl b/Templates/Notice/3.tpl index e1e06190..9d62d8f7 100644 --- a/Templates/Notice/3.tpl +++ b/Templates/Notice/3.tpl @@ -7,7 +7,7 @@ # - Reduced redundant queries ################################################################################# -$dataarray = explode(",", $message->readingNotice['data']); +$dataarray = array_map('tz_expand_report', explode(",", $message->readingNotice['data'])); // ======================== CONFIG ======================== $hasHero = (isset($dataarray[184]) && $dataarray[184] > 0); @@ -82,7 +82,7 @@ if ($database->isVillageOases($dataarray[29])) { procMtime($message->readingNotice['time']); ?> - + @@ -117,7 +117,7 @@ for ($i = $start; $i <= ($start + 9); $i++) { } if ($hasHero) { - echo "\"Hero\""; + echo "\"".RC_HERO."\""; } echo "".TROOPS.""; diff --git a/Templates/Notice/8.tpl b/Templates/Notice/8.tpl index 7a9b8333..d6cd9b27 100644 --- a/Templates/Notice/8.tpl +++ b/Templates/Notice/8.tpl @@ -7,7 +7,7 @@ # - Minor stability fixes ################################################################################# -$dataarray = explode(",", $message->readingNotice['data']); +$dataarray = array_map('tz_expand_report', explode(",", $message->readingNotice['data'])); // ======================== CONFIG ======================== $hasHero = (!empty($dataarray[13]) && $dataarray[13] > 0); @@ -62,7 +62,7 @@ if ($fromName != "[?]" || $fromId == 0) { procMtime($message->readingNotice['time']); ?> - + @@ -100,7 +100,7 @@ for ($i = $start; $i <= ($start + 9); $i++) { // hero column if ($hasHero) { - echo "\"Hero\""; + echo "\"".RC_HERO."\""; } echo "".TROOPS."";