Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENHANCEMENT] Prepare previously Hard-Coded Texts for Localization Support #3985

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

KoloInDaCrib
Copy link
Contributor

@KoloInDaCrib KoloInDaCrib commented Jan 10, 2025

Description

Inspired by a comment by Eric about the translations being lower in the priority list due to some obstacles. This PR aims to well overcome those obstacles
It introduces a new class, FunkinText, which is an extension of FlxText. Basically what it does is every time text (or font!) get updated, it checks whether or not the current font has glyphs for all the characters in the text. If not, the font Arial is used (subject to change maybe i dunno lol), as it is supposed to have most of the characters due to often being the default font
This PR also hooks up a lot of previously hard-coded texts to a single .json file, texts.json. It's placed exactly where introText.txt is, in the assets/data folder. Eric mentioned in the comment linked above that Polymod has been upgraded with a locales feature, so now every time a locale is loaded, it should also load the texts.json file for that locale, so voilla, translation support hell yeah!

Contents of the JSON file

The texts.json file is split into two "groups" per se - "title" and the rest.

The "title" part

The "title" part refers to the sequence that happens at the start of the game - basically making it soft-codeable now. It has two fields, "randomTextSplitter" and "texts".

"randomTextSplitter" is a String Field that dictates what the wacky random texts are split by - defaulting to "--". This means that the texts in the introText.txt file are split by "--" to indicate a line break.

The field "texts" is an array of anonymous structures, with required fields being "beat" and "command". "beat" represents at what beat should the command happen and is an integer value. "command" is basically what should happen when the "beat" happens. It's possible values are:

  • "show-text": Shows the multilined text. For all the source code nerds out there it call the function "createCoolText" in TitleState
  • "append-text": Appends the text to the current one (i.e. calls "addMoreText"), it's separate from the previous because addMoreText also makes the Haptic vibrate ??? No clue what that is lol
  • "clear-text": Gets rid of the awesome texts rest in peace
  • "show-logo": Shows the NG logo if it ain't null
  • "hide-logo": The antithesis of the previous entry
  • "finish-intro": Also known as the default value if for some reason we don't succeed! Self explanatory methinks

The optional values to the anonymous structure are "texts", which is an array of strings representing what texts to display, if at all, and "randomText", which is an integer value indicating which part of the randomly chosen line (separated via randomTextSplitter!) to show, if at all. Random Lines have a higher priority than "texts"!

The rest

Alright now for the rest part. This one is a little more tricky. Basically because I could not stand making three gajillion predetermined typedefs for text organisation, so the data from the texts.json file is actually a Dynamic value! That means that any organisation of texts is entirely dependant on the person and it won't toggle any errors! For example, this is an excerp of the .json file with previously hard-coded texts related to freeplay menu

"freeplay": {
    "title": "FREEPLAY",
    "ost": "OFFICIAL OST",
    "charSelectHint:": "Press [ ${value} ] to change characters"
  },

Lets say we want to get the text from the field "ost". To do that, we would simply need to use Texts.instance.getText("freeplay/ost"). The slash is indicative of the subgroups n shit. Though be aware! If the command doesn't detect either of the fields "freeplay" or ost (nested inside "freeplay") or if "freeplay/ost" is not a string, it returns null! This system is great for null checks and keeping my sanity in place!

A keen eye might have noticed "${value}". That is a macro more or less. So basically some texts require additional fields to operate, like the charSelectHint text with the control. The macro is there so that it could automatically be replaced with a replacer. To get a text that should have a replacer, simply run Texts.instance.getText([daPath], [daArrayOfValues]). In this case, if we run the aforementioned command with the values ["balls"] we would receive the text "Press [ balls ] to change characters"!

One may wonder why the replacer values are an array instead of a dynamic value. Simply put, during my research to put in as many hard-coded texts I came across one text that required TWO values, eeyikes! To combat it, I had to use arrays. Though what about the macros, one may wonder. Worry not because I have a solution!

Let's say we have a text Pico Erect was played by pico-christmas at the location "test/results". Now we could replace "Pico Erect" and "pico-christmas" with the aforementioned macro ${value}, though they both would be linked to one value. If we instead did ${value1} was played by ${value2} we now have macros for two values! And if we want to get the text, we would run Texts.instance.getText("test/results", ["Pico Erect", "pico-christmas"]). By doing so, we get exactly what we would needed! Hooray!!

Additional Things that I could do but I'm not sure whether or not I should do that

  • Hook up Controls to the json
  • Hook up Difficulty Names to the json
  • Hook up Week and Song Names to the json
  • Hook up everything related to the Debug Menu (that being chart and stage editor texts) to the json
  • Add a title command to reroll random text
  • probably more but i dont remember

Conclusion

tired af lol anyways if any of this was too confusing to you take a gander at the texts.json file and the code! Perhaps it would be more understandable
ill add footage later kinda busy atm

@github-actions github-actions bot added size: large A large pull request with more than 100 changes. pr: haxe PR modifies game code. and removed size: large A large pull request with more than 100 changes. labels Jan 10, 2025
@EliteMasterEric EliteMasterEric added the status: pending triage Awaiting review. label Jan 17, 2025
@EliteMasterEric
Copy link
Member

I like FunkinText, that's pretty useful, but for the actual localization handling, we plan to use FireTongue, which has close integration with Polymod. It hasn't updated in a bit since I'm the maintainer and haven't worked on translation in a while, but we definitely want to use that instead of your solution. It has a lot of good features like advanced variable replacement.

@EliteMasterEric EliteMasterEric added status: needs revision Cannot be approved because it is awaiting some work by the contributor. type: enhancement Involves an enhancement or new feature. and removed status: pending triage Awaiting review. labels Jan 17, 2025
@KoloInDaCrib
Copy link
Contributor Author

I like FunkinText, that's pretty useful, but for the actual localization handling, we plan to use FireTongue, which has close integration with Polymod. It hasn't updated in a bit since I'm the maintainer and haven't worked on translation in a while, but we definitely want to use that instead of your solution. It has a lot of good features like advanced variable replacement.

I see, looks quite interesting and pretty much covers everything from this pr. However I noticed the "needs revision" label and I'm curious as to whether you're referring to the checklist of things that I could do (which is mostly just more hooking up texts) or something else entirely.

Also should I keep this to only soft-coded intro sequence since FireTongue obviously cannot cover that and it would be somewhat useful for modders?

@EliteMasterEric
Copy link
Member

Also should I keep this to only soft-coded intro sequence since FireTongue obviously cannot cover that and it would be somewhat useful for modders?

Firetongue + Polymod has a way of handling asset files (like introText.txt). I'll probably just reject this PR and implement localization myself when we're ready to do the work of localizing other assets (like the main menu text).

EDIT: I still like FunkinText, so I'll probably just cherry pick that when I get around to it.

@Hundrec Hundrec added the size: large A large pull request with more than 100 changes. label Jan 22, 2025
@AbnormalPoof
Copy link
Collaborator

This PR appears to have merge conflicts. Please fix them!

@MidyGamy
Copy link
Contributor

WAIT!!! HAXEUI ALREADY HAVE A LOCALIZATION TOOL!!!

@EliteMasterEric
Copy link
Member

WAIT!!! HAXEUI ALREADY HAVE A LOCALIZATION TOOL!!!

We'd probably use that for the chart editor and use Polymod's system for other stuff.

@AbnormalPoof
Copy link
Collaborator

If this PR gets rejected, then I'd love to see FunkinText in a separate PR. It seems really useful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr: haxe PR modifies game code. size: large A large pull request with more than 100 changes. status: needs revision Cannot be approved because it is awaiting some work by the contributor. type: enhancement Involves an enhancement or new feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants