
You can see an example here. Or see how it is build below.
Format:¶
Project.xml
- source
|_ PlayState.hx
|_ Main.hx
- assets
|_ data
|_ lang
|_ ar.json
|_ de.json
|_ en.json
|_ es.json
|_ fr.json
|_ it.json
|_ pt.json
|_ ru.json
|_ zh.json
Project.xml¶
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://lime.software/project/1.0.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://lime.software/project/1.0.2 http://lime.software/xsd/project-1.0.2.xsd">
<!-- _________________________ Application Settings _________________________ -->
<app title="LangExample" file="LangExample" main="Main" version="0.0.1" company="SantiagoCalebe" />
<!--The flixel preloader is not accurate in Chrome. You can use it regularly if you embed the swf into a html file
or you can set the actual size of your file manually at "FlxPreloaderBase-onUpdate-bytesTotal"-->
<app preloader="flixel.system.FlxPreloader" />
<!--Minimum without FLX_NO_GAMEPAD: 11.8, without FLX_NO_NATIVE_CURSOR: 11.2-->
<set name="SWF_VERSION" value="11.8" />
<!-- ____________________________ Window Settings ___________________________ -->
<!--These window settings apply to all targets-->
<window width="640" height="360" fps="60" background="#000000" hardware="true" vsync="false" />
<!--HTML5-specific-->
<window if="html5" resizable="false" />
<!--Desktop-specific-->
<window if="desktop" orientation="landscape" fullscreen="false" resizable="true" />
<!--Mobile-specific-->
<window if="mobile" orientation="landscape" fullscreen="true" width="0" height="0" />
<!-- _____________________________ Path Settings ____________________________ -->
<set name="BUILD_DIR" value="export" />
<source path="source" />
<assets path="assets" />
<assets path="assets/data/lang" rename="assets/data/lang" include="*.json" />
<!-- _______________________________ Libraries ______________________________ -->
<haxelib name="flixel" />
<haxelib name="flixel-addons" />
<haxelib name="hxLang" />
<!--In case you want to use the ui package-->
<!--<haxelib name="flixel-ui" />-->
<!--In case you want to use nape with flixel-->
<!--<haxelib name="nape-haxe4" />-->
<!-- ______________________________ Haxedefines _____________________________ -->
<!--Enable the Flixel core recording system-->
<!--<haxedef name="FLX_RECORD" />-->
<!--Disable the right and middle mouse buttons-->
<!--<haxedef name="FLX_NO_MOUSE_ADVANCED" />-->
<!--Disable the native cursor API on Flash-->
<!--<haxedef name="FLX_NO_NATIVE_CURSOR" />-->
<!--Optimise inputs, be careful you will get null errors if you don't use conditionals in your game-->
<haxedef name="FLX_NO_MOUSE" if="mobile" />
<haxedef name="FLX_NO_KEYBOARD" if="mobile" />
<haxedef name="FLX_NO_TOUCH" if="desktop" />
<!--<haxedef name="FLX_NO_GAMEPAD" />-->
<!--Disable the Flixel core sound tray-->
<!--<haxedef name="FLX_NO_SOUND_TRAY" />-->
<!--Disable the Flixel sound management code-->
<!--<haxedef name="FLX_NO_SOUND_SYSTEM" />-->
<!--Disable the Flixel core focus lost screen-->
<!--<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />-->
<!--Disable the Flixel core debugger. Automatically gets set whenever you compile in release mode!-->
<haxedef name="FLX_NO_DEBUG" unless="debug" />
<!--Enable this for Nape release builds for a serious peformance improvement-->
<haxedef name="NAPE_RELEASE_BUILD" unless="debug" />
<!-- _________________________________ Custom _______________________________ -->
<!--Place custom nodes like icons here (higher priority to override the HaxeFlixel icon)-->
</project>
source/Main.hx¶
package;
import flixel.FlxGame;
import flixel.FlxG;
import flixel.FlxState;
import openfl.display.Sprite;
import PlayState;
import hxLang.Lang;
class Main extends Sprite
{
public var languages:Array<String> = ["en", "es", "fr", "de", "pt", "it", "ru", "zh", "ja", "ar"];
public function new()
{
super();
Lang.init("assets/data/lang", languages, true);
Lang.setDefaultLang("en");
var game = new FlxGame(640, 480, PlayState, 60, 60);
addChild(game);
}
}
source/PlayState.hx¶
package;
import flixel.FlxState;
import flixel.text.FlxText;
import flixel.FlxSprite;
import flixel.FlxG;
import hxLang.Lang;
class PlayState extends FlxState {
var langFields:Array<FlxSprite> = [];
var langLabels:Array<FlxText> = [];
var quoteField:FlxText;
var footerText:FlxText;
var languages = Lang.langs();
var selectedIndex:Int = 0;
override public function create():Void {
super.create();
Lang.switchLanguage(languages[selectedIndex]);
quoteField = new FlxText(0, 0, 400, Lang.get("quote"));
quoteField.wordWrap = true;
quoteField.setFormat(null, 18, 0xFFFFFFFF, "left");
quoteField.screenCenter();
quoteField.x += 100;
add(quoteField);
for (i in 0...languages.length) {
var lang = languages[i];
var bg = new FlxSprite(0, 30 + i * 35);
bg.makeGraphic(150, 30, 0xFF444444);
bg.alpha = (i == selectedIndex) ? 1 : 0.5;
add(bg);
langFields.push(bg);
var langStr = Std.string(lang);
var label = new FlxText(bg.x + 5, bg.y + 5, 140, langStr.toUpperCase());
label.setFormat(null, 20, (i == selectedIndex) ? 0xFFFFFFFF : 0xFF888888, "left");
add(label);
langLabels.push(label);
}
footerText = new FlxText(0, 0, FlxG.width, "© SantiagoCalebe - hxLang (2025 -)", 16);
footerText.setFormat(null, 16, 0xFFFFFFFF, "center");
footerText.y = FlxG.height - footerText.height - 10;
footerText.scrollFactor.set();
add(footerText);
}
override public function update(elapsed:Float):Void {
super.update(elapsed);
var hoveredIndex:Int = -1;
for (i in 0...langFields.length) {
if (FlxG.mouse.overlaps(langFields[i])) {
hoveredIndex = i;
break;
}
}
for (i in 0...langFields.length) {
var isSelected = (i == selectedIndex);
var isHovered = (i == hoveredIndex);
if (isHovered) {
langFields[i].alpha = 1;
langFields[i].makeGraphic(150, 30, 0xFFFFFFFF);
langLabels[i].color = 0xFFFFFFFF;
if (FlxG.mouse.justPressed) {
if (selectedIndex != i) {
selectedIndex = i;
var lang = languages[i];
if (Lang.switchLanguage(lang)) {
quoteField.text = Lang.get("quote");
}
}
}
} else if (isSelected) {
langFields[i].alpha = 1;
langFields[i].makeGraphic(150, 30, 0xFFFFFFFF);
langLabels[i].color = 0xFF000000;
} else {
langFields[i].alpha = 0.5;
langFields[i].makeGraphic(150, 30, 0xFF444444);
langLabels[i].color = 0xFF888888;
}
}
}
}
And also, in assets/data/lang/, there is 10 JSON files with the languages.
assets/json/data/ar.json¶
{
"currentLanguage": "Arabic",
"quote": "Nahnu mahkumuna bi'an nakuna ahraran."
}
assets/json/data/de.json¶
{
"currentLanguage": "Deutsch",
"quote": "Wir sind dazu verurteilt, frei zu sein."
}
assets/json/data/en.json¶
{
"currentLanguage": "English",
"quote": "We are condemned to be free."
}
assets/json/data/es.json¶
{
"currentLanguage": "Español",
"quote": "Estamos condenados a ser libres."
}
assets/json/data/fr.json¶
{
"currentLanguage": "Français",
"quote": "Nous sommes condamnés à être libres."
}
assets/json/data/it.json¶
{
"currentLanguage": "Italiano",
"quote": "Siamo condannati a essere liberi."
}
assets/json/data/pt.json¶
{
"currentLanguage": "Português",
"quote": "Estamos condenados a ser livres."
}
assets/json/data/ru.json¶
{
"currentLanguage": "Russian",
"quote": "My obrecheny byt' svobodnymi."
}
assets/json/data/zh.json¶
{
"currentLanguage": "Chinese",
"quote": "Women zhuding yao ziyou."
}