Skip to content

Instantly share code, notes, and snippets.

@nadako
Created July 21, 2015 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nadako/086124686083ce122b28 to your computer and use it in GitHub Desktop.
Save nadako/086124686083ce122b28 to your computer and use it in GitHub Desktop.
Type-safe localization.
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
class LocaleMacro {
static function build():Array<Field> {
var fields = Context.getBuildFields();
var newFields:Array<Field> = [];
for (field in fields) {
switch (field.kind) {
case FVar(t, null):
field.kind = FProp("get", "never", t);
newFields.push({
pos: field.pos,
name: "get_" + field.name,
access: [APrivate, AStatic, AInline],
kind: FFun({
ret: macro : String,
args: [],
expr: macro return LocaleStorage.localize($v{field.name}, null)
})
});
case FFun(fun):
var args = [];
for (arg in fun.args)
args.push(macro $v{arg.name} => $i{arg.name});
field.kind = FFun({
ret: fun.ret,
args: fun.args,
expr: macro return LocaleStorage.localize($v{field.name}, $a{args})
});
default:
throw new Error("Invalid field type. Should be either string var or a function", field.pos);
}
field.access = [APublic, AStatic];
}
return fields.concat(newFields);
}
}
class LocaleStorage {
public static var data:Map<String,String>;
public static function localize(key:String, args:Map<String,String>):String {
var s = data[key];
if (s == null)
return 'NOT LOCALIZED: $key';
if (args == null)
return s;
var r = ~/\{(\w+)\}/;
var buf = new StringBuf();
while (true) {
if (r.match(s)) {
buf.add(r.matchedLeft());
var v = args[r.matched(1)];
if (v == null)
v = "NO VALUE";
buf.add(v);
s = r.matchedRight();
} else {
buf.add(s);
break;
}
}
return buf.toString();
}
}
@:build(LocaleMacro.build())
class Locale {
var some_object_name:String;
var some_window_title:String;
function some_window_message(object_name:String):String;
}
class Main {
static function main() {
LocaleStorage.data = [
"some_object_name" => "ъжсло",
"some_window_title" => "пепяка",
"some_window_message" => "погладь {object_name}, сука!",
];
trace(Locale.some_window_title);
trace(Locale.some_window_message(Locale.some_object_name));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment