@@ -12,8 +12,9 @@ use super::pb;
1212
1313pub use error_details:: { vec:: ErrorDetail , ErrorDetails } ;
1414pub use std_messages:: {
15- BadRequest , DebugInfo , ErrorInfo , FieldViolation , Help , HelpLink , PreconditionFailure ,
16- PreconditionViolation , QuotaFailure , QuotaViolation , RequestInfo , ResourceInfo , RetryInfo ,
15+ BadRequest , DebugInfo , ErrorInfo , FieldViolation , Help , HelpLink , LocalizedMessage ,
16+ PreconditionFailure , PreconditionViolation , QuotaFailure , QuotaViolation , RequestInfo ,
17+ ResourceInfo , RetryInfo ,
1718} ;
1819
1920trait IntoAny {
@@ -446,6 +447,28 @@ pub trait StatusExt: crate::sealed::Sealed {
446447 /// }
447448 /// ```
448449 fn get_details_help ( & self ) -> Option < Help > ;
450+
451+ /// Get first [`LocalizedMessage`] details found on `tonic::Status`, if
452+ /// any. If some `prost::DecodeError` occurs, returns `None`.
453+ ///
454+ /// # Examples
455+ ///
456+ /// ```
457+ /// use tonic::{Status, Response};
458+ /// use tonic_types::StatusExt;
459+ ///
460+ /// fn handle_request_result<T>(req_result: Result<Response<T>, Status>) {
461+ /// match req_result {
462+ /// Ok(_) => {},
463+ /// Err(status) => {
464+ /// if let Some(localized_message) = status.get_details_localized_message() {
465+ /// // Handle localized_message details
466+ /// }
467+ /// }
468+ /// };
469+ /// }
470+ /// ```
471+ fn get_details_localized_message ( & self ) -> Option < LocalizedMessage > ;
449472}
450473
451474impl crate :: sealed:: Sealed for tonic:: Status { }
@@ -497,6 +520,10 @@ impl StatusExt for tonic::Status {
497520 conv_details. push ( help. into_any ( ) ) ;
498521 }
499522
523+ if let Some ( localized_message) = details. localized_message {
524+ conv_details. push ( localized_message. into_any ( ) ) ;
525+ }
526+
500527 let details = gen_details_bytes ( code, & message, conv_details) ;
501528
502529 tonic:: Status :: with_details_and_metadata ( code, message, details, metadata)
@@ -545,6 +572,9 @@ impl StatusExt for tonic::Status {
545572 ErrorDetail :: Help ( help) => {
546573 conv_details. push ( help. into_any ( ) ) ;
547574 }
575+ ErrorDetail :: LocalizedMessage ( loc_message) => {
576+ conv_details. push ( loc_message. into_any ( ) ) ;
577+ }
548578 }
549579 }
550580
@@ -600,6 +630,9 @@ impl StatusExt for tonic::Status {
600630 Help :: TYPE_URL => {
601631 details. help = Some ( Help :: from_any ( any) ?) ;
602632 }
633+ LocalizedMessage :: TYPE_URL => {
634+ details. localized_message = Some ( LocalizedMessage :: from_any ( any) ?) ;
635+ }
603636 _ => { }
604637 }
605638 }
@@ -645,6 +678,9 @@ impl StatusExt for tonic::Status {
645678 Help :: TYPE_URL => {
646679 details. push ( Help :: from_any ( any) ?. into ( ) ) ;
647680 }
681+ LocalizedMessage :: TYPE_URL => {
682+ details. push ( LocalizedMessage :: from_any ( any) ?. into ( ) ) ;
683+ }
648684 _ => { }
649685 }
650686 }
@@ -781,6 +817,20 @@ impl StatusExt for tonic::Status {
781817
782818 None
783819 }
820+
821+ fn get_details_localized_message ( & self ) -> Option < LocalizedMessage > {
822+ let status = pb:: Status :: decode ( self . details ( ) ) . ok ( ) ?;
823+
824+ for any in status. details . into_iter ( ) {
825+ if any. type_url . as_str ( ) == LocalizedMessage :: TYPE_URL {
826+ if let Ok ( detail) = LocalizedMessage :: from_any ( any) {
827+ return Some ( detail) ;
828+ }
829+ }
830+ }
831+
832+ None
833+ }
784834}
785835
786836#[ cfg( test) ]
@@ -789,8 +839,8 @@ mod tests {
789839 use tonic:: { Code , Status } ;
790840
791841 use super :: {
792- BadRequest , DebugInfo , ErrorDetails , ErrorInfo , Help , PreconditionFailure , QuotaFailure ,
793- RequestInfo , ResourceInfo , RetryInfo , StatusExt ,
842+ BadRequest , DebugInfo , ErrorDetails , ErrorInfo , Help , LocalizedMessage ,
843+ PreconditionFailure , QuotaFailure , RequestInfo , ResourceInfo , RetryInfo , StatusExt ,
794844 } ;
795845
796846 #[ test]
@@ -812,7 +862,8 @@ mod tests {
812862 . add_bad_request_violation ( "field" , "description" )
813863 . set_request_info ( "request-id" , "some-request-data" )
814864 . set_resource_info ( "resource-type" , "resource-name" , "owner" , "description" )
815- . add_help_link ( "link to resource" , "resource.example.local" ) ;
865+ . add_help_link ( "link to resource" , "resource.example.local" )
866+ . set_localized_message ( "en-US" , "message for the user" ) ;
816867
817868 let fmt_details = format ! ( "{:?}" , err_details) ;
818869
@@ -830,6 +881,7 @@ mod tests {
830881 RequestInfo :: new( "request-id" , "some-request-data" ) . into( ) ,
831882 ResourceInfo :: new( "resource-type" , "resource-name" , "owner" , "description" ) . into( ) ,
832883 Help :: with_link( "link to resource" , "resource.example.local" ) . into( ) ,
884+ LocalizedMessage :: new( "en-US" , "message for the user" ) . into( ) ,
833885 ] ;
834886
835887 let fmt_details_vec = format ! ( "{:?}" , err_details_vec) ;
0 commit comments