Localization - text files, selective sound assets

Hello,

I’m just wondering if and how this is possible with jME:

I plan to make a Localization feature with different text files and sound assets.

I know that there is this Java feature called property files - are the packed when exporting the executables?
I would like to use unicode text files and bundle them together with my game in a folder like “assets/Text/”.

The sound files for speeches on the other hand, will be quite large.
So I need a way to only bundle one or two languages together with the exported executable.
For instance, I will have speeches in English and German and for the international version I want to export English speech sounds only.

Thanks for any help or hints,

You can make a zip file (or an assets directory) for each language with the sound files named in the same way

eg.
en.zip:
Hello.ogg
Bye.ogg

de.zip:
Hello.ogg
Bye.ogg

And load the appropriate zip file according with the user’s language setting with this method: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:beginner:hello_asset#loading_assets_from_custom_paths

For the text files, i think you can’t load plain text with the assetManager, so you have to use normal java apis (FileInputStream, Scanner)

1 Like
@Riccardo said: You can make a zip file (or an assets directory) for each language with the sound files named in the same way

eg.
en.zip:
Hello.ogg
Bye.ogg

de.zip:
Hello.ogg
Bye.ogg

And load the appropriate zip file according with the user’s language setting with this method: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:beginner:hello_asset#loading_assets_from_custom_paths

That’s a nice (and simple) idea. It would also make it easier for the users to plug in their own speech files for bonus content or different languages! :slight_smile:

@Riccardo said: For the text files, i think you can't load plain text with the assetManager, so you have to use normal java apis (FileInputStream, Scanner)

I have another (and very odd) idea: Why not load text as textures and interpret RGBA colors as two unicode characters? :slight_smile:
I would simply have to write a little converter that switches between those two worlds at runtime (easy) and keep some reference alive (this might be the harder part).
Also, the runtime cost of access to textures might be high, so better save the text and unload it to free memory.
The text would also profit from zip / texture compression when on disk - which keeps the disk impact low.

But a better way would be to write my own manager. Hm… so many things to do… so little time.

I have another (and very odd) idea: Why not load text as textures and interpret RGBA colors as two unicode characters? :) I would simply have to write a little converter that switches between those two worlds at runtime (easy) and keep some reference alive (this might be the harder part). Also, the runtime cost of access to textures might be high, so better save the text and unload it to free memory. The text would also profit from zip / texture compression when on disk - which keeps the disk impact low.

But a better way would be to write my own manager. Hm… so many things to do… so little time.


:lol: That is really leet, but you won’t get any benefits considering that you can compress/decompress with java.util.zip.* as well.
I suggest you to use Object Serialization for write and load arrays directly.

@Riccardo said: :lol: That is really leet, but you won't get any benefits considering that you can compress/decompress with java.util.zip.* as well. I suggest you to use Object Serialization for write and load arrays directly.

Hm, maybe this texture-idea would even be faster than standard serialization, if I make it clever.
Would have to compare this to normal Object serialization.
The size would be okay too - a 1024x1024 rgba texture can represent 2,096,152 unicode chars.
It costs 4 Megabytes and would be enough maybe for one whole language text…

I plan to get my stuff to work on Android too, which I’ve never developed for.
Might be that multiple external files won’t be possible with smartphones.
Google recently made their “external data policy” more restricted.
But many advanced games would save/load savefgames and that must be possible on Android too, I guess.
At least a simple high score should be savable there.
I wonder how Android game programmers do this at the moment.

You can load anything you want through the asset manager provided you give it a locator and/or loader for that type. Really I don’t see any advantage (and many many many disadvantages) to trying to encode some weird text thing into a textures.

Okay, here are some advantages / disadvantages that I see:

One possible advantage would be, that everything gets loaded really fast via hardware buffers, in one swipe. No fractured snippets that issue a disk read each item.

Another advantage might be that I don’t have to write any loader or locator classes.

Another advantage is, that the export process of the SDK packages my texture files as zipped png images - again I don’t need any special build script magic. And this build script stuff is a personal enemy of mine. :wink:

One disadvantage might be that there is different Endianness on different systems, perhaps. A test would tell.

I would have to test this idea in practice to see if this works.
And of course I would have to deactivate texture compression for this texture image or I only get rubbish.

What are the disadvantages that you suspect?

And for the Endianness I could programm a simple fix: If I know the first letter (let this be an “A”) I could find out if I get an “A” or something swivelled (not an “A”). Then set the Endianness compensator mode to true and un-swivel everything or load the alternative texture “texttexture_swivelled.png”. :slight_smile:

Loading a text file from a jar (without assetManager) is like 2 lines of code…

@Ogli said: Okay, here are some advantages / disadvantages that I see:

One possible advantage would be, that everything gets loaded really fast via hardware buffers, in one swipe. No fractured snippets that issue a disk read each item.

Nope. There is no way to control this. If images are bigger than a certain size then there will be multiple low level reads. Plus, the alternative “storing this non image data in an image” isn’t “store a text file”. It’s “store it however you find most efficient”.

You would have to store it in a lossless format like PNG… and PNG compression is designed for images and not text. Where as there is a compression that was specifically designed with text in mind…

@Ogli said: Another advantage might be that I don't have to write any loader or locator classes.

Which would be trivial compared to writing the utility to encode text into an image and then decode it again. Your fear of the unknown is making you consider crazy things. “I’ve never driven to the store before so I paid someone to construct one in my back yard so I don’t have to. Easy!”

@Ogli said: Another advantage is, that the export process of the SDK packages my texture files as zipped png images - again I don't need any special build script magic. And this build script stuff is a personal enemy of mine. ;-)

Anything in the assets directory gets zipped into the assets jar. There is nothing special you have to do.

@Ogli said: One disadvantage might be that there is different Endianness on different systems, perhaps. A test would tell.

I would have to test this idea in practice to see if this works.
And of course I would have to deactivate texture compression for this texture image or I only get rubbish.

What are the disadvantages that you suspect?

Disadvantage:
-writing tricky (potentially bug-filled) code to translate UTF into image data and back
-using a file format designed for other things to store text
-inefficient text compression because of PNG encoding.
-writing some tools to let you easily build these files
-loading a whole texture?!? with all of the disadvantages therein just to get at some data.

I’m trying to be nice about this but the whole idea is kind of patently ridiculous.

All of that work just to avoid a few lines in an AssetLoader. :slight_smile:

Okay, when the time has come, I will give both ideas (yours and mine) a try.

FYI:
It’s not the fear of the unknown. I know that I will have to do a full reverse engineering to understand jME completely.
But just some looks into the many build script files that come with the SDK was the pure horror.
Also this is work that I typically would like to avoid according to the mantra “make games, not engines”.
But I won’t run away to other engines.
Don’t panic! :wink:

Sorry, must continue working on my awesome jME-based game. I want it complete when this week is over.

@Ogli said: Okay, when the time has come, I will give both ideas (yours and mine) a try.

FYI:
It’s not the fear of the unknown. I know that I will have to do a full reverse engineering to understand jME completely.
But just some looks into the many build script files that come with the SDK was the pure horror.
Also this is work that I typically would like to avoid according to the mantra “make games, not engines”.
But I won’t run away to other engines.
Don’t panic! :wink:

Sorry, must continue working on my awesome jME-based game. I want it complete when this week is over.

You might as well mention 50 other “hard” yet unrelated things… since messing with build files has nothing to do with this conversation, really.

If you have to reverse engineer JME to figure out how to make a custom loader then you are doing something wrong.

http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/AssetLoader.html

There are dozens of hints at code samples to look at right there.

http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/AssetManager.html#registerLoader(java.lang.Class,%20java.lang.String...)

The clues were already mentioned a few times in this thread but I felt I should be very specific. :wink:

I suggest doing separate asset jar files, with the same file names but different content, similar to what Ogli suggested. At some point the SDK will support this natively, also for different platforms (GUI xml files, j3m Material files etc.) ANT isn’t very complicated to learn, really. Maybe the future gradle projects will make it easier for some but I bet some will also complain that its more complicated.

@normen said: I suggest doing separate asset jar files, with the same file names but different content, similar to what Ogli suggested.

Credits for this idea goes to Riccardo. :slight_smile:

The idea is not so very new anyways - FMod (sound software) does things this way. It exports the same filenames for different platforms with different content. And it uses a similar mapping for localization of speech files. The content has the same name, but goes into different folders with different encodings - it generates files for the last-gen gaming consoles in their native format and for PC you can select .mp3, .ogg, .wav encoding and even specify the sampling quality.
FMod even goes one step further and let’s you define meta-sound-effects: On PC they might be comprised of three audio layers, on handhelds there is only one sound layer which reduces CPU and memory footprint.
Managing all those speeches and their according subtitle text files is quite a job too.

@pspeed said: You might as well mention 50 other "hard" yet unrelated things... The clues were already mentioned a few times in this thread but I felt I should be very specific. ;)

Yeah, thanks for the hints. I must admit, you are somewhat right with your criticism.
I hope that I can return the favor when I finally post my commit (there will be monkeys in my game!). :slight_smile:

The idea isn’t new at all, its one of the reasons why we want a GUI system with descriptor files for the UI instead of code. Its a good solution for various similar issues. I just mention it because there seem to be constant attempts to reinvent this wheel.

My attempt for this would simply the devaul java i18n behaviour.

I would define a default “language” with the english textures named to a key,
then eg for german I would create additional images with replaced text, and add a german file

This way I simply need to extend the default Locators with one that does an additional loocup into the RessourceBundle, and then calls the default super logic with the translated name.

  • bonus points if the different languages except english are split into own jars, so the users can provide own files for non supported languages in the community

http://www.java2s.com/Code/Java/I18N/JavaI18NIntroduction.htm

yes , it’s the same thing that nifty-gui does with resource bundle tags . Unless you want to implement something wired you should rely to Gui support for this kind of things . Or follow their behavior to implement something that wouldn’t require a Gui . ( Idk , localize also some game models ).

@normen said: I just mention it because there seem to be constant attempts to reinvent this wheel.

Yeah, I know what you mean - it’s a nasty thing.

But many things must be done for certain simple things to achieve with jME.
On the other hand I found many “utils” and “plugins” that already do some of the things that I want, with some drawbacks and imperfections.

There are certain people who really push the jME project - like you already do with NetBeans and Ant stuff.
I hope to publish my project to the community soon - but I might need help to get my project transformed into a plugin for the SDK.

As for the initial topic:
Management of text and speeches is such a universal thing in today’s game industry.
I hope to see improvements in support like @normen already sketched some ideas.
Otherwise I will be forced to “reinvent the wheel” and share that code wih jME community.
FMod (what I mentioned) is not a viable solution, because these guys want to see money and it’s propriatary. Also it only manages sounds, not text databases.
Some time ago I sketched a solution for Localization management, that includes author privilege management and user-assitance (automatic TODO-lists and context info).