The use of the data argument #426
Replies: 5 comments
-
After digging a bit in the code, I've found I can resolve the properties from the F.e. I'm using it to translate resources in my template. The helper looks like this: private static void TranslateHelper(in EncodedTextWriter writer, in HelperOptions options, in Context ctx, in Arguments args)
{
if (args.Length < 1 || !(args[0] is string caption))
return;
if (!string.IsNullOrWhiteSpace(caption) && options.Data["Translations"] is ResourceSet translations)
{
caption = translations.GetString(caption) ?? caption;
if (args.Length > 1)
caption = string.Format(caption, args.Skip(1).ToArray());
}
writer.WriteSafeString(caption);
} Example usage: [Fact]
public void Create_TranslateHelper_ShouldTranslateByKeyAndReplaceParameters()
{
// Arrange
var templateData = new TranslateData("Jos", "De bosklapper");
ResourceSet translations = ResourceManager.GetResourceSet(new CultureInfo("nl-BE"), createIfNotExists: true, tryParents: true);
// Act
IHandlebars handlebars = HandlebarsFactory.Create();
HandlebarsTemplate<object, object> template = handlebars.Compile("<p>{{translate '{0} has shared the project \"{1}\" with you' inviter projectName}}.</p>");
string result = template(templateData, new { Translations = translations });
// Assert
result.Should().Be("<p>Jos heeft het project \"De bosklapper\" met jou gedeeld.</p>");
} Is this how it should be used? |
Beta Was this translation helpful? Give feedback.
-
Hello @huysentruitw
|
Beta Was this translation helpful? Give feedback.
-
Thanks for the info. Another question I had: Currently, my templates look like this:
Can I change my helper, so it would work like this?
So after replacing the translation, I'm looking for a way to get the resulting string evaluated, so inviter and projectName gets resolved. Is that possible? |
Beta Was this translation helpful? Give feedback.
-
Hello @huysentruitw Unfortunately usage you mention is not quite possible at this time. [Fact]
public void Translate()
{
var handlebars = Handlebars.Create();
var source = "{{{{translate}}}} 1 {{value}} 2 {{{{/translate}}}}";
handlebars.RegisterHelper("translate", (output, options, context, arguments) =>
{
var translation = options.Template();
translation = translation
.Replace("1", "3")
.Replace("2", "4");
// maybe add cache for translated templates
var env = (IHandlebars) options.Data["env"];
output.WriteSafeString(env.Compile(translation)(options.Frame));
});
var template = handlebars.Compile(source);
// creating separate env with expression interpratation instead of compilation should speedup execution in this scenario
var passedEnv = Handlebars.Create();
passedEnv.Configuration.CompileTimeConfiguration.Features.Add(new InterpretationCompilerFeature());
var result = template(
new { value = 42 },
new { env = passedEnv }
);
Assert.Equal(" 3 42 4 ", result);
}
/// <summary>
/// Uses interpretation instead of compilation. Eliminates delegate compilation overhead of one-time templates.
/// However template compiled this way would execute slower
/// </summary>
internal class InterpretationCompilerFeature : IFeature, IFeatureFactory
{
public void OnCompiling(ICompiledHandlebarsConfiguration configuration)
{
configuration.ExpressionCompiler = new InterpretationExpressionCompiler(configuration.ExpressionMiddlewares);
}
public void CompilationCompleted()
{
// noting to do here
}
private class InterpretationExpressionCompiler : IExpressionCompiler
{
private readonly IReadOnlyList<IExpressionMiddleware> _expressionMiddleware;
public InterpretationExpressionCompiler(IReadOnlyList<IExpressionMiddleware> expressionMiddlewares)
{
_expressionMiddleware = expressionMiddlewares;
}
public T Compile<T>(Expression<T> expression) where T: class, Delegate
{
// -- section
// this section may be omitted in case you do not plan to execute any complex expressions as part of `translate` helper
// removing it may save you some time during translated expression compilation
for (var index = 0; index < _expressionMiddleware.Count; index++)
{
expression = _expressionMiddleware[index].Invoke(expression);
}
// -- section
return expression.Compile(true);
}
}
public IFeature CreateFeature() => this;
} |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for this information! I think I'll keep using my string.Format approach and use |
Beta Was this translation helpful? Give feedback.
-
When compiling a template, we get back a
HandlebarsTemplate<object, object>
delegate instance.That delegate can be called with the
context
, which is the data being used in the template. But what about theTData data
argument we can pass in there? What is the use? And can we access it from a helper method?Beta Was this translation helpful? Give feedback.
All reactions