WIP Translation

This commit is contained in:
NeeEoo
2024-04-12 14:11:09 +02:00
parent 69080bbfa7
commit 9cf4c903ad
22 changed files with 333 additions and 171 deletions
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<language>
<group name="General Editor Translations">
<str id="editor.autosavingIn">Autosaving in {0} seconds{1}</str>
</group>
<group name="ChartEditor">
<str id="charter.name">Chart Editor</str>
<str id="charter.addEvent">Add Event</str>
<str id="charter.editEvent">Edit</str> <!-- Should maybe be "Edit Event" -->
<str id="charter.deleteEvent">Delete Event</str>
</group>
<group name="CharacterEditor">
<str id="charEditor.name">Character Editor</str>
</group>
<group name="StageEditor">
<str id="stageEditor.name">Stage Editor</str>
</group>
<!-- Debug Options here maybe?-->
</language>
+96
View File
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8" ?>
<language>
<group name="PlayState">
<str id="game.score">Score:{0}</str>
<str id="game.misses">Misses:{0}</str>
<str id="game.comboBreaks">Combo Breaks:{0}</str>
<str id="game.accuracy">Accuracy:{0} - {1}</str>
<str id="game.combo">Combo:{0}</str>
<str id="game.rating.[N/A]">[N/A]</str>
<str id="game.rating.F">F</str>
<str id="game.rating.E">E</str>
<str id="game.rating.D">D</str>
<str id="game.rating.C">C</str>
<str id="game.rating.B">B</str>
<str id="game.rating.A">A</str>
<str id="game.rating.S">S</str>
<str id="game.rating.S++">S++</str>
</group>
<group name="PlayTesting">
<str id="playtesting.chartPlaytesting" notrim="true"> (Chart Playtesting)</str>
<str id="playtesting.exitGame">Exit Game</str>
<str id="playtesting.exitToMenu">Exit To Menu</str>
<str id="playtesting.saveAndExitGame">Save &amp; Exit Game</str>
<str id="playtesting.saveAndExitToMenu">Save &amp; Exit To Menu</str>
<str id="playtesting.cancel">Cancel</str>
<str id="playtesting.warningTitle">UNSAVED CHANGES!</str>
<str id="playtesting.warningDesc">Your changes will be *lost* if you don't save them. (Can't be recovered)\n\n\nWould you like to Cancel?</str>
</group>
<group name="StoryMenu">
<str id="story.score">WEEK SCORE:{0}</str>
<str id="story.tracks">TRACKS</str>
</group>
<group name="Freeplay">
<str id="freeplay.score">PERSONAL BEST:{0}</str>
<str id="freeplay.solo">Solo</str>
<str id="freeplay.opponentMode">Opponent Mode</str>
<str id="freeplay.coopMode">Co-Op Mode</str>
<str id="freeplay.coopModeSwitched">Co-Op Mode (Switched)</str>
</group>
<group name="Pause">
<group name="PauseOptions">
<!-- These dont work yet-->
<str id="pause.resume">Resume</str>
<str id="pause.restart">Restart Song</str>
<str id="pause.changeControls">Change Controls</str>
<str id="pause.changeOptions">Change Options</str>
<str id="pause.exitToMenu">Exit to menu</str>
<str id="pause.exitToCharter">Exit to charter</str>
</group>
<str id="pause.deathCounter">Blue balled: {0}</str>
<str id="pause.coopMode">CO-OP MODE</str>
<str id="pause.opponentMode">OPPONENT MODE</str>
</group>
<group name="Credits">
<group name="CreditsCodename">
<str id="credits.mainDev" notrim="true"> *- Public member of the main Devs!*</str>
<str id="credits.totalContributions">Total Contributions: ~{0}~ / *{1}* (~{2}%~) - Select to open GitHub account</str>
<str id="credits.downloadingList">Downloading List...</str>
<str id="credits.allContributors">All the contributors of the engine! - Press RESET to update the list (One reset per 2 minutes).</str>
</group>
<group name="CreditsMain">
<str id="credits.name">Credits</str>
<str id="credits.madePossible">The people who made this possible!</str>
<str id="credits.selectCodename">Select this to see all the contributors of the engine!</str>
<str id="credits.selectBase">Select this to open the itch.io page of the original game to donate!</str>
</group>
</group>
<group name="Mods">
<str id="mods.disableMods">Disable Mods</str>
</group>
<group name="MainMenu">
<str id="mainMenu.commit">Commit: {0} ({1})</str>
<str id="mainMenu.openMods">[{0}] Open Mods menu</str>
</group>
<group name="BetaWarning">
<str id="betaWarning.title">WARNING</str>
<str id="betaWarning.desc">This engine is still in a *{0}* state. That means *majority of the features* are either *buggy* or *non finished*. If you find any bugs, please report them to the Codename Engine GitHub.\n\nPress {1} to continue</str>
</group>
<group name="Difficulties">
<str id="diff.easy">Easy</str>
<str id="diff.normal">Normal</str>
<str id="diff.hard">Hard</str>
</group>
</language>
+3
View File
@@ -0,0 +1,3 @@
name="English"
credits="Codename Engine"
version="0.0.1"
+2 -17
View File
@@ -2,19 +2,10 @@ package funkin.backend;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.util.FlxColor;
import funkin.backend.utils.TranslationUtil.IFormatInfo;
class FunkinText extends FlxText {
public var langStrID:String = null;
private var langFormat:IFormatInfo;
public function new(X:Float = 0, Y:Float = 0, FieldWidth:Float = 0, ?Text:String, Size:Int = 16, Border:Bool = true, ?LangStrID:String, ?Parameters:Array<Dynamic>) {
langStrID = LangStrID;
langFormat = TranslationUtil.getUnformatted(Text, LangStrID);
// Should still default to the normal string if the translation is not found
super(X, Y, FieldWidth, getFormattedText(Parameters), Size);
public function new(X:Float = 0, Y:Float = 0, FieldWidth:Float = 0, ?Text:String, Size:Int = 16, Border:Bool = true) {
super(X, Y, FieldWidth, Text, Size);
setFormat(Paths.font("vcr.ttf"), Size, FlxColor.WHITE);
if (Border) {
borderStyle = OUTLINE;
@@ -22,10 +13,4 @@ class FunkinText extends FlxText {
borderColor = 0xFF000000;
}
}
public inline function resetLang(Parameters:Array<Dynamic>)
return this.text = getFormattedText(Parameters);
private inline function getFormattedText(Parameters:Array<Dynamic>)
return langFormat.format(Parameters);
}
@@ -94,6 +94,11 @@ class Script extends FlxBasic implements IFlxDestroyable {
"EngineUtil" => funkin.backend.utils.EngineUtil,
"MemoryUtil" => funkin.backend.utils.MemoryUtil,
"BitmapUtil" => funkin.backend.utils.BitmapUtil,
#if TRANSLATIONS_SUPPORT
"TranslationUtil" => funkin.backend.utils.TranslationUtil,
"translate" => funkin.backend.utils.TranslationUtil.get,
#end
];
}
public static function getDefaultPreprocessors():Map<String, Dynamic> {
+7
View File
@@ -742,6 +742,13 @@ class CoolUtil
return array.indexOf(element) != -1;
}
#end
public static inline function repeat(str:String, times:Int) {
var r = new StringBuf();
for(i in 0...times)
r.add(str);
return r.toString();
}
}
/**
+25 -105
View File
@@ -7,6 +7,7 @@ import openfl.utils.Assets;
import haxe.io.Path;
import haxe.xml.Access;
import haxe.Exception;
import funkin.backend.utils.translations.FormatUtil;
/**
* The class used for translations based on the XMLs inside the translations folders.
@@ -14,7 +15,7 @@ import haxe.Exception;
* Made by @NexIsDumb originally for the Poldhub mod.
*/
@:allow(funkin.backend.assets.TranslatedAssetLibrary)
class TranslationUtil
final class TranslationUtil
{
/**
* The current language selected translation map; If the current language it's english, this map will be empty.
@@ -63,7 +64,7 @@ class TranslationUtil
private static inline function getDefaultNameMap():Map<String, String> {
return ['en' => 'English'];
}
private static inline function getDefaultConfig(name:String):IniMap {
@:noUsing private static inline function getDefaultConfig(name:String):IniMap {
return ["name" => getLanguageName(name), "credits" => "", "version" => "1.0.0"];
}
@@ -98,16 +99,22 @@ class TranslationUtil
*
* If `id` is `null` then it's gonna search using `defString`.
*/
public static inline function get(defString:String, ?id:String, ?params:Array<Dynamic>):String
return getUnformatted(defString, id).format(params);
public static inline function get(?id:String, ?params:Array<Dynamic>, ?def:String):String
return getUnformatted(id, def).format(params);
public static function getUnformatted(defString:String, ?id:String):IFormatInfo
public static inline function translate(?id:String, ?params:Array<Dynamic>, ?def:String):String
return get(id, params, def);
public static inline function translateDiff(?id:String, ?params:Array<Dynamic>):String
return get("diff." + id.toLowerCase(), params, id);
public static function getUnformatted(id:String, ?def:String):IFormatInfo
{
#if TRANSLATIONS_SUPPORT
if (id == null) id = defString;
if (stringMap.exists(id)) return stringMap.get(id);
#end
return FormatUtil.get(defString);
if(def != null) id = def;
return FormatUtil.get(id);
}
/**
@@ -146,6 +153,8 @@ class TranslationUtil
if (foundLanguages.contains(englishName))
foundLanguages.remove(englishName);
foundLanguages.insert(0, englishName);
Logs.trace("Found languages: " + foundLanguages.join(", "), "Language");
#end
}
@@ -163,17 +172,19 @@ class TranslationUtil
for(node in xml.elements) {
if (node.name == "group") // Cosmetic name
parseXml(node);
else if(node.name == "text" || node.name == "trans" || node.name == "lang" || node.name == "string")
else if(["text", "trans", "lang", "string", "str"].contains(node.name))
translations.push(node);
}
}
for(file in Paths.getFolderContent(mainPath, true).sortAlphabetically()) {
if(Path.extension(file) != "xml") continue;
if(Path.extension(file).toLowerCase() != "xml") continue;
var afile = "assets/" + file;
// Parse the XML
var xml:Access = null;
try xml = new Access(Xml.parse(Assets.getText(file)))
try xml = new Access(Xml.parse(Assets.getText(afile)))
catch(e) Logs.error('Error while parsing $file: ${Std.string(e)}', "Language");
if (xml == null) continue;
@@ -197,9 +208,13 @@ class TranslationUtil
continue;
}
var shouldTrim = node.has.notrim ? node.att.notrim != "true" : true;
var value:String = node.has.string ? node.att.string : node.innerData;
value = shouldTrim ? value.trim() : value;
value = value.replace("\\n", "\n").replace("\r", ""); // remove stupid windows line breaks and convert newline literals to newlines
leMap.set(node.att.id, FormatUtil.get(value));
//Logs.trace("Added " + node.att.id + " -> `" + value + "`", "Language");
}
return leMap;
@@ -256,99 +271,4 @@ class TranslationUtil
@:noCompletion private static function get_isLanguageLoaded():Bool
return Lambda.count(stringMap) > 0;
}
/**
* The class used to format strings based on parameters.
*
* For example if the parameter list is just an `Int` which is `9`, `You have been blue balled {0} times` becomes `You have been blue balled 9 times`.
*/
class FormatUtil {
private static var cache:Map<String, IFormatInfo> = new Map();
public static function get(id:String):IFormatInfo {
if (cache.exists(id))
return cache.get(id);
var fi:IFormatInfo = ParamFormatInfo.returnOnlyIfValid(id);
if(fi == null) fi = new StrFormatInfo(id);
cache.set(id, fi);
return fi;
}
public inline static function clear() {
cache.clear();
}
}
class StrFormatInfo implements IFormatInfo {
public var string:String;
public function new(str:String) {
this.string = str;
}
public function format(params:Array<Dynamic>):String {
return string;
}
public function toString():String {
return "StrFormatInfo(" + string + ")";
}
}
// TODO: add support for @:({0}==1?(Hello):(World))
class ParamFormatInfo implements IFormatInfo {
public var strings:Array<String> = [];
public var indexes:Array<Int> = [];
public function new(str:String) {
var i = 0;
while (i < str.length) {
var fi = str.indexOf("{", i); // search from the start of i
if (fi == -1) {
// if there are no more parameters, just add the rest of the string
this.strings.push(str.substring(i));
break;
}
var fe = str.indexOf("}", fi);
this.strings.push(str.substring(i, fi));
this.indexes.push(Std.parseInt(str.substring(fi+1, fe)));
i = fe + 1;
}
}
public static function isValid(str:String):Bool {
var fi = new ParamFormatInfo(str);
return fi.indexes.length > 0;
}
public static function returnOnlyIfValid(str:String):IFormatInfo {
var fi = new ParamFormatInfo(str);
return fi.indexes.length > 0 ? fi : null;
}
public function format(params:Array<Dynamic>):String {
if (params == null) params = [];
var str:String = "";
for (i=>s in strings) {
str += s;
if (i < indexes.length)
str += params[indexes[i]];
}
return str;
}
public function toString():String {
return 'ParamFormatInfo([${strings.join(", ")}] [${indexes.join(", ")}])';
}
}
interface IFormatInfo {
public function format(params:Array<Dynamic>):String;
}
@@ -0,0 +1,96 @@
package funkin.backend.utils.translations;
/**
* The class used to format strings based on parameters.
*
* For example if the parameter list is just an `Int` which is `9`, `You have been blue balled {0} times` becomes `You have been blue balled 9 times`.
*/
class FormatUtil {
private static var cache:Map<String, IFormatInfo> = new Map();
public static function get(id:String):IFormatInfo {
if (cache.exists(id))
return cache.get(id);
var fi:IFormatInfo = ParamFormatInfo.returnOnlyIfValid(id);
if(fi == null) fi = new StrFormatInfo(id);
cache.set(id, fi);
return fi;
}
public inline static function clear() {
cache.clear();
}
}
class StrFormatInfo implements IFormatInfo {
public var string:String;
public function new(str:String) {
this.string = str;
}
public function format(params:Array<Dynamic>):String {
return string;
}
public function toString():String {
return "StrFormatInfo(" + string + ")";
}
}
// TODO: add support for @:({0}==1?(Hello):(World))
class ParamFormatInfo implements IFormatInfo {
public var strings:Array<String> = [];
public var indexes:Array<Int> = [];
public function new(str:String) {
var i = 0;
while (i < str.length) {
var fi = str.indexOf("{", i); // search from the start of i
if (fi == -1) {
// if there are no more parameters, just add the rest of the string
this.strings.push(str.substring(i));
break;
}
var fe = str.indexOf("}", fi);
this.strings.push(str.substring(i, fi));
this.indexes.push(Std.parseInt(str.substring(fi+1, fe)));
i = fe + 1;
}
}
public static function isValid(str:String):Bool {
var fi = new ParamFormatInfo(str);
return fi.indexes.length > 0;
}
public static function returnOnlyIfValid(str:String):IFormatInfo {
var fi = new ParamFormatInfo(str);
return fi.indexes.length > 0 ? fi : null;
}
public function format(params:Array<Dynamic>):String {
if (params == null) params = [];
var str:String = "";
for (i=>s in strings) {
str += s;
if (i < indexes.length)
str += params[indexes[i]];
}
return str;
}
public function toString():String {
return 'ParamFormatInfo([${strings.join(", ")}] [${indexes.join(", ")}])';
}
}
interface IFormatInfo {
public function format(params:Array<Dynamic>):String;
}
@@ -26,7 +26,7 @@ class CharterAutoSaveUI extends UISliceSprite {
icon.animation.play("icon"); icon.animation.curAnim.curFrame = 0;
members.push(icon);
members.push(autosavingText = new UIText(x+12+10+4, y+8, 0, "Autosaving in 10 seconds...", 12));
members.push(autosavingText = new UIText(x+12+10+4, y+8, 0, TU.translate("editor.autosavingIn", ["?", "..."]), 12));
progressBarBack = new FlxSprite(x + 10, y + bHeight - 20).makeGraphic(Std.int(bWidth-20), 10, 0x00000000, true);
progressBarBack.drawRoundRect(0, 0, progressBarBack.width, progressBarBack.height, 4, 6, 0xFF727272, null, {smoothing: false});
@@ -68,8 +68,10 @@ class CharterAutoSaveUI extends UISliceSprite {
__tween = FlxTween.num(0, 1, time, null, (v:Float) -> {
if ((progress = v) < .95) {
autosavingText.text = 'Autosaving in ${Math.min(Math.round(time), 1+Math.floor(Math.abs(time-(progress*time))))} seconds';
autosavingText.text += [for (i in 0...(Math.floor((progress*time*3)%4))) "."].join("");
autosavingText.text = TU.translate("editor.autosavingIn", [
Math.min(Math.round(time), 1+Math.floor(Math.abs(time-(progress*time)))),
".".repeat(Math.floor((progress*time*3)%4))
]);
}
});
__timer = new FlxTimer();
@@ -109,7 +111,7 @@ class CharterAutoSaveUI extends UISliceSprite {
}
public function appearAnimation() {
autosavingText.text = "Autosaving in seconds..."; progress = 0; icon.animation.curAnim.curFrame = 0;
progress = 0; icon.animation.curAnim.curFrame = 0;
for (member in [this, autosavingText, progressBar, progressBarBack]) member.color = 0xFFFFFFFF;
x = -(320); alpha=0; FlxTween.cancelTweensOf(this); cancelled = false; cancelButton.visible = true;
@@ -38,7 +38,7 @@ class CharterEventAdd extends UISliceSprite {
curCharterEvent = null;
this.step = step;
this.y = (step * 40) - (bHeight / 2);
text.text = "Add event";
text.text = TU.translate("editors.addEvent");
framesOffset = 0;
x = -(bWidth = 37 + Math.ceil(text.width));
}
@@ -46,7 +46,7 @@ class CharterEventAdd extends UISliceSprite {
public function updateEdit(event:CharterEvent) {
curCharterEvent = event;
this.y = event.y;
text.text = "Edit";
text.text = TU.translate("editors.editEvent");
framesOffset = 9;
x = -(bWidth = 27 + Math.ceil(text.width) + event.bWidth);
}
+11 -11
View File
@@ -719,9 +719,9 @@ class PlayState extends MusicBeatState
add(icon);
}
scoreTxt = new FunkinText(healthBarBG.x + 50, healthBarBG.y + 30, Std.int(healthBarBG.width - 100), "Score:{0}", 16, "score", [songScore]);
missesTxt = new FunkinText(healthBarBG.x + 50, healthBarBG.y + 30, Std.int(healthBarBG.width - 100), "Misses:0", 16);
accuracyTxt = new FunkinText(healthBarBG.x + 50, healthBarBG.y + 30, Std.int(healthBarBG.width - 100), "Accuracy:{0} - {1}", 16, "accuracy", ["-%", "(N/A)"]);
scoreTxt = new FunkinText(healthBarBG.x + 50, healthBarBG.y + 30, Std.int(healthBarBG.width - 100), TU.translate("game.score", [songScore]), 16);
missesTxt = new FunkinText(healthBarBG.x + 50, healthBarBG.y + 30, Std.int(healthBarBG.width - 100), TU.translate("game.misses", [misses]), 16);
accuracyTxt = new FunkinText(healthBarBG.x + 50, healthBarBG.y + 30, Std.int(healthBarBG.width - 100), TU.translate("game.accuracy", ["-%", "(N/A)"]), 16);
accuracyTxt.addFormat(accFormat, 0, 1);
for(text in [scoreTxt, missesTxt, accuracyTxt]) {
@@ -751,7 +751,7 @@ class PlayState extends MusicBeatState
if (chartingMode) {
WindowUtils.prefix = Charter.undos.unsaved ? "* " : "";
WindowUtils.suffix = " (Chart Playtesting)";
WindowUtils.suffix = TU.translate("charter.chartPlaytesting");
SaveWarning.showWarning = Charter.undos.unsaved;
SaveWarning.selectionClass = CharterSelection;
@@ -1141,7 +1141,7 @@ class PlayState extends MusicBeatState
state.openSubState(new PlaytestingWarningSubstate(closingWindow, [
{
label: closingWindow ? "Exit Game" : "Exit To Menu",
label: closingWindow ? TU.translate("playtesting.exitGame") : TU.translate("playtesting.exitToMenu"),
color: 0xFF0000,
onClick: function(_) {
if (!closingWindow) {
@@ -1153,7 +1153,7 @@ class PlayState extends MusicBeatState
}
},
{
label: closingWindow ? "Save & Exit Game" : "Save & Exit To Menu",
label: closingWindow ? TU.translate("playtesting.saveAndExitGame") : TU.translate("playtesting.saveAndExitToMenu"),
color: 0xFFFF00,
onClick: function(_) {
if (SaveWarning.saveFunc != null) SaveWarning.saveFunc();
@@ -1166,7 +1166,7 @@ class PlayState extends MusicBeatState
}
},
{
label: "Cancel",
label: TU.translate("playtesting.cancel"),
color: 0xFFFFFF,
onClick: function (_) {
if (closingWindow) WindowUtils.resetClosing();
@@ -1190,15 +1190,15 @@ class PlayState extends MusicBeatState
}
function updateRatingStuff() {
scoreTxt.resetLang([songScore]);
missesTxt.text = '${comboBreaks ? "Combo Breaks" : "Misses"}:$misses';
scoreTxt.text = TU.translate("game.score", [songScore]);
missesTxt.text = TU.translate(comboBreaks ? "game.comboBreaks" : "game.misses", [misses]);
if (curRating == null)
curRating = new ComboRating(0, "[N/A]", 0xFF888888);
@:privateAccess {
accFormat.format.color = curRating.color;
accuracyTxt.resetLang([accuracy < 0 ? "-%" : '${CoolUtil.quantize(accuracy * 100, 100)}%', curRating.rating]);
accuracyTxt.text = TU.translate("game.accuracy", [accuracy < 0 ? "-%" : '${CoolUtil.quantize(accuracy * 100, 100)}%', curRating.rating]);
accuracyTxt._formatRanges[0].range.start = accuracyTxt.text.length - curRating.rating.length;
accuracyTxt._formatRanges[0].range.end = accuracyTxt.text.length;
@@ -1914,7 +1914,7 @@ class ComboRating {
public function new(percent:Float, rating:String, color:FlxColor) {
this.percent = percent;
this.rating = TranslationUtil.get(rating, 'rating_$rating');
this.rating = TranslationUtil.get('game.rating.$rating', rating);
this.color = color;
}
}
+1
View File
@@ -6,6 +6,7 @@ import funkin.backend.MusicBeatSubstate;
import funkin.backend.MusicBeatGroup;
import funkin.backend.FunkinSprite;
import funkin.backend.utils.*;
import funkin.backend.utils.TranslationUtil as TU;
import funkin.backend.system.Logs;
import funkin.options.Options;
import funkin.game.PlayState;
+2 -2
View File
@@ -13,13 +13,13 @@ class BetaWarningState extends MusicBeatState {
public override function create() {
super.create();
titleAlphabet = new Alphabet(0, 0, "WARNING", true);
titleAlphabet = new Alphabet(0, 0, TU.translate("betaWarning.title"), true);
titleAlphabet.screenCenter(X);
add(titleAlphabet);
disclaimer = new FunkinText(16, titleAlphabet.y + titleAlphabet.height + 10, FlxG.width - 32, "", 32);
disclaimer.alignment = CENTER;
disclaimer.applyMarkup('This engine is still in a *${Main.releaseCycle}* state. That means *majority of the features* are either *buggy* or *non finished*. If you find any bugs, please report them to the Codename Engine GitHub.\n\nPress ENTER to continue',
disclaimer.applyMarkup(TU.translate("betaWarning.desc", [Main.releaseCycle, "ENTER"]),
[
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF4444), "*")
]
+7 -7
View File
@@ -48,7 +48,7 @@ class FreeplayState extends MusicBeatState
/**
* Currently lerped score. Is updated to go towards `intendedScore`.
*/
public var lerpScore:Int = 0;
public var lerpScore:Float = 0;
/**
* Destination for the currently lerped score.
*/
@@ -207,7 +207,7 @@ class FreeplayState extends MusicBeatState
FlxG.sound.music.volume += 0.5 * elapsed;
}
lerpScore = Math.floor(lerp(lerpScore, intendedScore, 0.4));
lerpScore = lerp(lerpScore, intendedScore, 0.4);
if (Math.abs(lerpScore - intendedScore) <= 10)
lerpScore = intendedScore;
@@ -220,7 +220,7 @@ class FreeplayState extends MusicBeatState
updateOptionsAlpha();
}
scoreText.text = "PERSONAL BEST:" + lerpScore;
scoreText.text = TU.translate("freeplay.score", [Math.round(lerpScore)]);
scoreBG.scale.set(Math.max(Math.max(diffText.width, scoreText.width), coopText.width) + 8, (coopText.visible ? coopText.y + coopText.height : 66));
scoreBG.updateHitbox();
scoreBG.x = FlxG.width - scoreBG.width;
@@ -344,10 +344,10 @@ class FreeplayState extends MusicBeatState
* Array containing all labels for Co-Op / Opponent modes.
*/
public var coopLabels:Array<String> = [
TranslationUtil.get("[TAB] Solo"),
TranslationUtil.get("[TAB] Opponent Mode"),
TranslationUtil.get("[TAB] Co-Op Mode"),
TranslationUtil.get("[TAB] Co-Op Mode (Switched)")
"[TAB] " + TU.translate("freeplay.solo"),
"[TAB] " + TU.translate("freeplay.opponentMode"),
"[TAB] " + TU.translate("freeplay.coopMode"),
"[TAB] " + TU.translate("freeplay.coopModeSwitched")
];
/**
+7 -1
View File
@@ -70,7 +70,13 @@ class MainMenuState extends MusicBeatState
FlxG.camera.follow(camFollow, null, 0.06);
var versionShit:FunkinText = new FunkinText(5, FlxG.height - 2, 0, 'Codename Engine v${Application.current.meta.get('version')}\nCommit ${funkin.backend.system.macros.GitCommitMacro.commitNumber} (${funkin.backend.system.macros.GitCommitMacro.commitHash})\n[TAB] Open Mods menu\n');
var versionText = [
'Codename Engine v${Application.current.meta.get('version')}',
TU.translate("mainMenu.commit", [funkin.backend.system.macros.GitCommitMacro.commitNumber, funkin.backend.system.macros.GitCommitMacro.commitHash]),
TU.translate("mainMenu.openMods", ["TAB"]),
''
].join('\n');
var versionShit:FunkinText = new FunkinText(5, FlxG.height - 2, 0, versionText);
versionShit.y -= versionShit.height;
versionShit.scrollFactor.set();
add(versionShit);
+1 -1
View File
@@ -27,7 +27,7 @@ class ModSwitchMenu extends MusicBeatSubstate {
alphabets = new FlxTypedGroup<Alphabet>();
for(mod in mods) {
var a = new Alphabet(0, 0, mod == null ? "DISABLE MODS" : mod, true);
var a = new Alphabet(0, 0, mod == null ? TU.translate("mods.disableMods") : mod, true);
a.isMenuItem = true;
a.scrollFactor.set();
alphabets.add(a);
+12 -7
View File
@@ -20,6 +20,7 @@ class PauseSubState extends MusicBeatSubstate
var grpMenuShit:FlxTypedGroup<Alphabet>;
// TODO: make it possible to translate these
var menuItems:Array<String> = ['Resume', 'Restart Song', 'Change Controls', 'Change Options', 'Exit to menu', "Exit to charter"];
var curSelected:Int = 0;
@@ -69,12 +70,19 @@ class PauseSubState extends MusicBeatSubstate
bg.scrollFactor.set();
add(bg);
var multiplayerInfo:String = PlayState.opponentMode ? 'pause.coopMode' :
PlayState.coopMode ? 'pause.opponentMode' :
null;
var levelInfo:FunkinText = new FunkinText(20, 15, 0, PlayState.SONG.meta.displayName, 32, false);
var levelDifficulty:FunkinText = new FunkinText(20, 15, 0, PlayState.difficulty.toUpperCase(), 32, false);
var multiplayerText:FunkinText = new FunkinText(20, 15, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32, false);
var deathCounter:FunkinText = new FunkinText(20, 15, 0, "Blue balled: {0}", 32, false, "blue_balled", [PlayState.deathCounter]);
var levelDifficulty:FunkinText = new FunkinText(20, 15, 0, TU.translateDiff(PlayState.difficulty).toUpperCase(), 32, false);
var deathCounter:FunkinText = new FunkinText(20, 15, 0, TU.translate("pause.deathCounter", [PlayState.deathCounter]), 32, false);
var multiplayerText:FunkinText = null;
if(multiplayerInfo != "")
multiplayerText = new FunkinText(20, 15, 0, TU.translate(multiplayerInfo), 32, false);
for(k=>label in [levelInfo, levelDifficulty, deathCounter, multiplayerText]) {
if(label == null) continue;
label.scrollFactor.set();
label.updateHitbox();
label.alpha = 0;
@@ -194,10 +202,7 @@ class PauseSubState extends MusicBeatSubstate
{
item.targetY = i - curSelected;
if (item.targetY == 0)
item.alpha = 1;
else
item.alpha = 0.6;
item.alpha = (item.targetY == 0) ? 1 : 0.6;
}
}
}
@@ -40,13 +40,13 @@ class PlaytestingWarningSubstate extends MusicBeatSubstate
bg.scrollFactor.set();
add(bg);
titleAlphabet = new Alphabet(0, 140, "UNSAVED CHANGES!", true);
titleAlphabet = new Alphabet(0, 140, TU.translate("playtesting.warningTitle"), true);
titleAlphabet.screenCenter(X);
add(titleAlphabet);
disclaimer = new FunkinText(16, titleAlphabet.y + titleAlphabet.height + 70, FlxG.width - 32, "", 32);
disclaimer.alignment = CENTER;
disclaimer.applyMarkup("Your changes will be *lost* if you don't save them. (Can't be recovered)\n\n\nWould you like to Cancel?",
disclaimer.applyMarkup(TU.translate("playtesting.warningDesc"),
[
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF4444), "*")
]
+14 -3
View File
@@ -48,7 +48,7 @@ class StoryMenuState extends MusicBeatState {
blackBar.color = 0xFF000000;
blackBar.updateHitbox();
scoreText = new FunkinText(10, 10, 0, "SCORE: -", 36);
scoreText = new FunkinText(10, 10, 0, TU.translate("story.score", ["-"]), 36);
scoreText.setFormat(Paths.font("vcr.ttf"), 32);
weekTitle = new FlxText(10, 10, FlxG.width - 20, "", 32);
@@ -125,7 +125,7 @@ class StoryMenuState extends MusicBeatState {
super.update(elapsed);
lerpScore = lerp(lerpScore, intendedScore, 0.5);
scoreText.text = 'WEEK SCORE:${Math.round(lerpScore)}';
scoreText.text = TU.translate("story.score", [Math.round(lerpScore)]);
if (canSelect) {
if (leftArrow != null && leftArrow.exists) leftArrow.animation.play(controls.LEFT ? 'press' : 'idle');
@@ -164,7 +164,18 @@ class StoryMenuState extends MusicBeatState {
for(k=>e in weekSprites.members) {
e.targetY = k - curWeek;
}
tracklist.text = 'TRACKS\n\n${[for(e in weeks[curWeek].songs) if (!e.hide) e.name.toUpperCase()].join('\n')}';
var str = new StringBuf();
str.add(TU.translate("story.tracks") + "\n\n");
var len = weeks[curWeek].songs.length;
for(i=>e in weeks[curWeek].songs) {
if (!e.hide) {
str.add(e.name.toUpperCase());
if (i != len-1)
str.add("\n");
}
}
tracklist.text = str.toString();
weekTitle.text = weeks[curWeek].name.getDefault("");
for(i in 0...3)
@@ -17,7 +17,7 @@ class CreditsCodename extends funkin.options.OptionsScreen {
public override function new()
{
super("Codename Engine", "All the contributors of the engine! - Press RESET to update the list (One reset per 2 minutes).");
super("Codename Engine", TU.translate("credits.allContributors"));
tryUpdating(true);
}
@@ -40,7 +40,7 @@ class CreditsCodename extends funkin.options.OptionsScreen {
}
public function tryUpdating(forceDisplaying:Bool = false) {
updateMenuDesc("Downloading List...");
updateMenuDesc(TU.translate("credits.downloadingList"));
_canReset = false;
Main.execAsync(function() {
if(checkUpdate() || forceDisplaying) _downloadingSteps = 2;
@@ -108,9 +108,10 @@ class CreditsCodename extends funkin.options.OptionsScreen {
totalContributions = 0;
for(c in Options.contributors) totalContributions += c.contributions;
for(c in Options.contributors) {
var opt:GithubIconOption = new GithubIconOption(c, 'Total Contributions: ~${c.contributions}~ / *${totalContributions}* (~${FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)}%~) - Select to open GitHub account');
var text = TU.translate("credits.totalContributions", [c.contributions, totalContributions, FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)]);
var opt:GithubIconOption = new GithubIconOption(c, text);
if(Options.mainDevs.contains(c.id)) {
opt.desc += " *- Public member of the main Devs!*";
opt.desc += TU.translate("credits.mainDev");
@:privateAccess opt.__text.color = mainDevCol;
}
add(opt);
+3 -3
View File
@@ -35,14 +35,14 @@ class CreditsMain extends TreeMenu {
selectables.push(c);
}
}
selectables.push(new TextOption("Codename Engine >", "Select this to see all the contributors of the engine!", function() {
selectables.push(new TextOption("Codename Engine >", TU.translate("credits.selectCodename"), function() {
optionsTree.add(Type.createInstance(CreditsCodename, []));
}));
selectables.push(new TextOption("Friday Night Funkin'", "Select this to open the itch.io page of the original game to donate!", function() {
selectables.push(new TextOption("Friday Night Funkin'", TU.translate("credits.selectBase"), function() {
CoolUtil.openURL("https://ninja-muffin24.itch.io/funkin");
}));
main = new OptionsScreen('Credits', 'The people who made this possible!', selectables);
main = new OptionsScreen(TU.translate("credits.name"), TU.translate("credits.madePossible"), selectables);
super.create();
DiscordUtil.call("onMenuLoaded", ["Credits Menu"]);
+2 -2
View File
@@ -78,11 +78,11 @@ class Alphabet extends FlxSpriteGroup
trace(e.details());
}
}
public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false, ?transID:String, ?transParams:Array<Dynamic>)
public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false)
{
super(x, y);
_finalText = this.text = TranslationUtil.get(text, transID, transParams);
_finalText = this.text = text;
isBold = bold;
var alphabetPath = Paths.xml("alphabet");