diff --git a/bin/cppcms_tmpl_cc b/bin/cppcms_tmpl_cc index 13094988..3aba6a1a 100755 --- a/bin/cppcms_tmpl_cc +++ b/bin/cppcms_tmpl_cc @@ -133,16 +133,21 @@ class view_block: output_declaration( "{") if self.uses!='' : output_declaration( "\t%s &content;" % self.uses) - output_declaration( "\t%s(std::ostream &_s,%s &_content): %s,content(_content)" % ( self.class_name,self.uses,constructor )) + output_declaration( "\t%s(std::ostream &_s,%s &_content): %s,content(_content),_domain_id(0)" % ( self.class_name,self.uses,constructor )) else: - output_declaration( "\t%s(std::ostream &_s): %s" % ( self.class_name,constructor )) + output_declaration( "\t%s(std::ostream &_s): %s,_domain_id(0)" % ( self.class_name,constructor )) output_declaration("\t{") global spec_gettext - if self.topmost and spec_gettext: - output_declaration('\t\tout() << cppcms::locale::as::domain("%s");' % spec_gettext ) + if spec_gettext: + self.gettext_domain = spec_gettext; + output_declaration( '\t\t_domain_id=cppcms::translation_domain_scope::domain_id(_s,"%s");' % self.gettext_domain) + else: + self.gettext_domain = None; output_declaration("\t}") def use(self,m): + global view_created + view_created = True self.abstract = m.group('abs')!=None self.inline = m.group('inline')!=None global view_name @@ -168,6 +173,8 @@ class view_block: if not self.abstract: class_list.append(information()) def on_end(self): + output_declaration( "private:") + output_declaration( "\tint _domain_id;") output_declaration( "}; // end of class %s" % self.class_name) @@ -215,9 +222,11 @@ class template_block: else: if inline_templates: output_declaration( "virtual void %s(%s) {" % (self.name,params) ) + output_declaration( "\tcppcms::translation_domain_scope _trs(out(),_domain_id);\n") else: output_declaration( "virtual void %s(%s);" % (self.name,params) ) output_definition( "void %s::%s(%s) {" % (view_name,self.name,params) ) + output_definition( "\tcppcms::translation_domain_scope _trs(out(),_domain_id);\n") global stack if len(stack)==0 or stack[-1].type!='view': error_exit("You must define template inside view block only") @@ -572,6 +581,24 @@ class error_com: error_exit("Invalid statement `%s'" % m.group(1)) +class domain_block: + pattern=r'^<%\s*domain\s+(\w+)\s*%>$' + basic_pattern = 'domain' + basic_name = 'domain' + type = 'domain' + def use(self,m): + gt = m.group(1) + global spec_gettext + global view_created + if not spec_gettext: + if view_created: + error_exit("Can't use domain command after a view was created") + else: + spec_gettext = gt + return + if spec_gettext != gt: + error_exit("Gettext domain is already defined as `%s' and differs from given `%s'" % (spec_gettext , gt )) + class cpp_include_block: pattern=r'^<%\s*c\+\+(src)?\s+(.*)%>$' basic_pattern = 'c\+\+(src)?' @@ -1167,6 +1194,7 @@ def main(): using_block(), \ render_block(), \ html_type(), form_block(), csrf_block(), \ + domain_block(), \ filters_show_block(), error_com() ]: basic_pattern = r'^<%\s*' + c.basic_pattern + r'.*%>$' @@ -1211,6 +1239,7 @@ exit_flag=0 current_template='' spec_gettext='' ignore_inline=1 +view_created=False scope_filter='cppcms::filters::escape' view_name = '' diff --git a/cppcms/filters.h b/cppcms/filters.h index 6e6477df..de8337a5 100644 --- a/cppcms/filters.h +++ b/cppcms/filters.h @@ -15,9 +15,42 @@ #include #include #include +#include +#include #include namespace cppcms { + /// + /// \brief set gettext domain id withing specific scope + /// + /// \ver{v1_2} + class CPPCMS_API translation_domain_scope : public booster::noncopyable { + public: + /// + /// Get numeric id for the domain + /// + static int domain_id(std::ostream &out,std::string const &domain); + + /// + /// Set domain id on the stream and save previous one to restore in the destructor + /// + translation_domain_scope(std::ostream &output,int domain_id); + /// + /// Set domain on the stream and save previous one to restore in the destructor + /// + translation_domain_scope(std::ostream &output,std::string const &domain); + /// + /// Restrore domain + /// + ~translation_domain_scope(); + private: + void set_and_save(int id); + struct _data; + booster::hold_ptr<_data> d; + std::ostream *output_; + int prev_id_; + }; + /// /// /// \brief This namespace various filters that can be used in templates for filtering data /// diff --git a/src/filters.cpp b/src/filters.cpp index 36f5d2b5..6fe0da80 100644 --- a/src/filters.cpp +++ b/src/filters.cpp @@ -12,7 +12,50 @@ #include #include -namespace cppcms { namespace filters { +namespace cppcms { + +struct translation_domain_scope::_data {}; + +void translation_domain_scope::set_and_save(int new_id) +{ + if(new_id < 0) + return; + booster::locale::ios_info &info = booster::locale::ios_info::get(*output_); + prev_id_ = info.domain_id(); + info.domain_id(new_id); +} + +int translation_domain_scope::domain_id(std::ostream &out,std::string const &dom) +{ + return std::use_facet >(out.getloc()).domain(dom); +} + +translation_domain_scope::translation_domain_scope(std::ostream &out,std::string const &dom) : + output_(&out), + prev_id_(-1) +{ + set_and_save(domain_id(out,dom)); +} + +translation_domain_scope::translation_domain_scope(std::ostream &out,int new_id) : + output_(&out), + prev_id_(-1) +{ + set_and_save(new_id); +} + +translation_domain_scope::~translation_domain_scope() +{ + if(prev_id_==-1) + return; + try { + booster::locale::ios_info::get(*output_).domain_id(prev_id_); + } + catch(...) {} +} + + +namespace filters { streamable::streamable() { diff --git a/tests/tc_plugin.tmpl b/tests/tc_plugin.tmpl index f81db3da..b8033406 100644 --- a/tests/tc_plugin.tmpl +++ b/tests/tc_plugin.tmpl @@ -1,5 +1,6 @@ <% c++ #include "tc_sep_skin.h" %> <% skin plugin %> +<% domain tc_plugin %> <% view master_plugin uses data::master extends tc_skin::master_api %> <% template m1() %>plugin::master_plugin::m1 <%= text %><% end %> <% end view %> diff --git a/tests/tc_plugin2.tmpl b/tests/tc_plugin2.tmpl index 681a89f3..efe17635 100644 --- a/tests/tc_plugin2.tmpl +++ b/tests/tc_plugin2.tmpl @@ -1,6 +1,12 @@ <% c++ #include "tc_sep_skin.h" %> +<% domain plugin %> <% skin plugin2 %> <% view master_plugin uses data::master extends tc_skin::master_api2 %> <% template call() %>Plugin2: <% include f1() %><% end %> <% end view %> + +<% view msg uses data::helper extends tc_skin::message_base %> +<% template render() %><% include f1() %>; <% gt "translate me" %>; <% include f1() %><% end %> +<% end view %> + <% end skin %> diff --git a/tests/tc_skin.tmpl b/tests/tc_skin.tmpl index 29a28d31..16acb5ed 100644 --- a/tests/tc_skin.tmpl +++ b/tests/tc_skin.tmpl @@ -241,6 +241,11 @@ TBD <% template h1() %>skin::helper_plugin::h1 <%= x %><% end %> <% end view %> +<% view message_base uses data::helper %> +<% template f1() %><% gt "translate me" %><% end %> +<% template render() %><% include f1() %><% end %> +<% end view %> + <% view test_master_plugin uses data::master %> <% template render() %> <% using master_api as m from "master_plugin" %><% include m1() from m %><% end using %>