У меня есть LangBuilder
макро класс;он используется для создания langObjects:Map<String, Dynamic>
текстов на разных языках во время компиляции и внедрения этой структуры в классы с помощью макроса @:build
.Каждый элемент карты имеет поле для каждого поддерживаемого языка.Таким образом, результат:
@:build(LangBuilder.build())
class Lang{}
trace(Lang.langObjects["hello-world"].en); //outputs "Hello World!"
trace(Lang.langObjects["hello-world"].it); //outputs "Ciao Mondo!"
Это работает отлично, но я подумал, что мог бы сделать работу чище, скрыв структуру langObjects
, используя функцию getLangText
с аргументами id текста (например, "hello-world"
) и код языка (например, "it"
).
Итак, я пытаюсь добавить эту функцию в классы:
public static function getLangText(id:String, lang:String)
Его немакрос версия может быть выражена как:
public static function getLangText(id:String, lang:String){
var _langObj_id = langObjects[id];
switch(lang){
case "it":
return _langObj_id.it;
case "en":
return _langObj_id.en;
}
return "Missing Translation";
Если я перевожу эту функцию как макрос с таким кодом:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
switch($i{"lang"}){
case "it":
return _langObj_id.it;
case "en":
return _langObj_id.en;
}
return "Missing translation";
};
var myFunc:Function = {
args: [{
name: "id",
type: TPath({name: "String", pack: []}),
meta: null
},
{
name: "lang",
type: TPath({name: "String", pack: []}),
meta: null
}],
ret: (macro:String),
expr: macro $code
};
fields.push({
pos: Context.currentPos(),
name: "getLangText",
meta: null,
kind: FieldType.FFun(myFunc),
doc: null,
access: [Access.APublic, Access.AStatic]
});
... она работает без проблем.Однако я хотел бы знать, как это можно написать без switch
, чтобы сделать его более гибким и узнать что-нибудь о макросах haxe.Я видел несколько примеров, когда к полям можно обращаться в макросах с $p{}
или с object.$fieldName
.Однако руководство haxe предупреждает, что вторая форма может использоваться только для простых идентификаторов;например object.${fieldName}
не будет работать.
Поэтому я пытаюсь этот код:
var code = macro {
var l:String = $i{"lang"};
var _langObj_id = langObjects[$i{"id"}];
return _langObj_id.$l;
};
Компилятор выдает ошибку
Неизвестный идентификатор: l
в строке, содержащей return _langObj_id.$l;
.
Затем я попытался использовать $p{}
reification:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
return macro $p{["_langObj_id", $i{"lang"}]};
};
Но ошибка похожа:
Неизвестный идентификатор: lang
Я, конечно, могу изменить структуру langObjects
на Map<String, Map<String, String>>
, а затем изменить код на:
var code = macro {
return macro langObjects[$i{"id"}][$i{"lang"}];
};
Я думаю,это сработало бы, но теперь я пытаюсь понять, почему и _langObj_id.$lang
, и $p{["_langObj_id", $i{"lang"}]}
не сработают, и каков будет правильный способ доступа к полю в такой ситуации.