Skip to content
Browse files

Compile-time translation of `{%trans%}` and `_(..)` by blocktrans_fun #…

…131

So, to fully translate template to multiple languages, we need just
blocktrans_fun and blocktrans_locales in compile-time.
No need for gettext server in runtime, to translate `trans` and `_(..)`.
  • Loading branch information...
1 parent aa23751 commit 1caea0562a2e1ecfd9920595b82f9ab5cc8fab2f @seriyps seriyps committed with kaos Feb 16, 2014
Showing with 38 additions and 12 deletions.
  1. +0 −1 include/erlydtl_ext.hrl
  2. +35 −10 src/erlydtl_compiler.erl
  3. +3 −1 tests/src/erlydtl_unittests.erl
View
1 include/erlydtl_ext.hrl
@@ -23,7 +23,6 @@
compiler_options = [],
binary_strings = true,
force_recompile = false,
- locale = none,
verbose = false,
is_compiling_dir = false,
extension_module = undefined,
View
45 src/erlydtl_compiler.erl
@@ -447,7 +447,7 @@ init_context(ParseTrail, DefDir, Module, Options) ->
compiler_options = proplists:append_values(compiler_options, Options),
binary_strings = proplists:get_value(binary_strings, Options, Ctx#dtl_context.binary_strings),
force_recompile = proplists:get_bool(force_recompile, Options),
- locale = proplists:get_value(locale, Options, Ctx#dtl_context.locale),
+ %% convert to blocktrans_locales locale = proplists:get_value(locale, Options, Ctx#dtl_context.locale),
verbose = proplists:get_value(verbose, Options, Ctx#dtl_context.verbose),
is_compiling_dir = ParseTrail == [],
extension_module = proplists:get_value(extension_module, Options, Ctx#dtl_context.extension_module),
@@ -1255,26 +1255,51 @@ translated_ast({string_literal, _, String}, Context, TreeWalker) ->
UnescapedStr = unescape_string_literal(String),
case call_extension(Context, translate_ast, [UnescapedStr, Context, TreeWalker]) of
undefined ->
- DefaultString = case Context#dtl_context.locale of
- none -> UnescapedStr;
- Locale -> erlydtl_i18n:translate(UnescapedStr,Locale)
- end,
- translated_ast2(erl_syntax:string(UnescapedStr), erl_syntax:string(DefaultString),
- #ast_info{translatable_strings = [UnescapedStr]}, TreeWalker);
+ AstInfo = #ast_info{translatable_strings = [UnescapedStr]},
+ case Context#dtl_context.blocktrans_fun of
+ none -> runtime_trans_ast(erl_syntax:string(UnescapedStr), AstInfo, TreeWalker);
+ _ -> compiletime_trans_ast(UnescapedStr, AstInfo, Context, TreeWalker)
+ end;
Translated ->
Translated
end;
translated_ast(ValueToken, Context, TreeWalker) ->
{{Ast, Info}, TreeWalker1} = value_ast(ValueToken, true, false, Context, TreeWalker),
- translated_ast2(Ast, Ast, Info, TreeWalker1).
+ runtime_trans_ast(Ast, Info, TreeWalker1).
-translated_ast2(UnescapedStrAst, DefaultStringAst, AstInfo, TreeWalker) ->
+runtime_trans_ast(ValueAst, AstInfo, TreeWalker) ->
StringLookupAst = erl_syntax:application(
erl_syntax:atom(erlydtl_runtime),
erl_syntax:atom(translate),
- [UnescapedStrAst, erl_syntax:variable("_TranslationFun"), DefaultStringAst]),
+ [ValueAst, erl_syntax:variable("_TranslationFun"), ValueAst]), %TODO: remove 3'rd arg
{{StringLookupAst, AstInfo}, TreeWalker}.
+compiletime_trans_ast(String, AstInfo,
+ #dtl_context{blocktrans_fun=TFun,
+ blocktrans_locales=TLocales}=Context,
+ TreeWalker) ->
+ {{DefaultAst, Info1}, TWalker1} = Default = string_ast(String, Context, TreeWalker),
+ DefaultClauseAst = erl_syntax:clause([erl_syntax:underscore()], none, [DefaultAst]), %or runtime trans?
+ FoldFun = fun(Locale, {ClausesAcc, Info2, TWalker2}) ->
+ {{TranslatedAst, Info3}, TWalker3} =
+ case TFun(String, Locale) of
+ default -> Default; %or runtime trans?
+ Translated ->
+ string_ast(binary_to_list(Translated), Context, TWalker2)
+ end,
+ ClauseAst = erl_syntax:clause(
+ [erl_syntax:string(Locale)],
+ none,
+ [TranslatedAst]),
+ {[ClauseAst | ClausesAcc], merge_info(Info2, Info3), TWalker3}
+ end,
+ {ClAst, ClInfo, ClTreeWalker} = lists:foldl(
+ FoldFun,
+ {[DefaultClauseAst], merge_info(AstInfo, Info1), TWalker1},
+ TLocales),
+ CaseAst = erl_syntax:case_expr(erl_syntax:variable("_CurrentLocale"), ClAst),
+ {{CaseAst, ClInfo}, ClTreeWalker}.
+
% Completely unnecessary in ErlyDTL (use {{ "{%" }} etc), but implemented for compatibility.
templatetag_ast("openblock", Context, TreeWalker) ->
string_ast("{%", Context, TreeWalker);
View
4 tests/src/erlydtl_unittests.erl
@@ -1163,7 +1163,9 @@ tests() ->
<<"Hello {% trans \"Hi\" %}">>, [], <<"Hello Hi">>
},
{"trans functional reverse locale",
- <<"Hello {% trans \"Hi\" %}">>, [], [], [{locale, "reverse"}], <<"Hello iH">>
+ <<"Hello {% trans \"Hi\" %}">>, [], [{locale, "reverse"}],
+ [{blocktrans_locales, ["reverse"]}, {blocktrans_fun, fun("Hi"=Key, "reverse") -> list_to_binary(lists:reverse(Key)) end}],
+ <<"Hello iH">>
},
{"trans literal at run-time",
<<"Hello {% trans \"Hi\" %}">>, [], [{translation_fun, fun("Hi") -> "Konichiwa" end}], [],

0 comments on commit 1caea05

Please sign in to comment.
Something went wrong with that request. Please try again.