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.
Uh oh!
There was an error while loading. Please reload this page.
-
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 dataargument 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