복붙노트

[SPRING] 커스텀 스프링 부트 스타터 : MessageSource에 i18n 메시지를 어떻게 기여합니까?

SPRING

커스텀 스프링 부트 스타터 : MessageSource에 i18n 메시지를 어떻게 기여합니까?

나는 다른 개발자가 자신의 응용 프로그램에 포함시킬 사용자 정의 Spring Boot 스타터를 작성 중이며,이 스타터에는 기본 컨트롤러와 UI 화면이 포함되어 있습니다.

이 UI 화면은 국제화되어 있고 i18n 키 / 값은 패키지 파일 : com / foo / wherever / i18n.properties에 있습니다.

시작시 스타터가 로딩 될 때 애플리케이션 개발자가 지정할 필요없이 UI 페이지가 정상적인 Spring Controller + ViewResolver + View 구현을 통해 렌더링되도록 애플리케이션의 MessageSource에서 이러한 i18n.properties를 자동으로 사용할 수 있도록하고 싶다. 이 파일 자체.

다른 말로하면, 그들은 자신의 런타임 클래스 경로에 내 시동기를 추가 할 수 있어야하며, 아무것도 구성 할 필요없이 모든 것이 '잘 작동합니다'.

이제 앱 개발자가 자신의 src / main / resources / messages.properties 파일을 만들고 application.properties에 수동으로 추가 메시지 파일을 구성 할 수 있음을 발견했습니다.

spring.messages.basename = messages, com.foo.wherever.i18n

그리고 이것은 효과가 있습니다.

그러나 이렇게하려면 다음 두 가지가 모두 필요합니다.

내 i18n.properties 파일을 classpath : /messages.properties 파일로 옮길 수 있다고 가정하지만, 좋은 해결책처럼 보이지는 않습니다 : 만약 앱 dev가 자신의 messages.properties 파일을 가지고 있다면 메시지 값이 누락 될 수 있습니다.

Spring Boot MessageSourceAutoConfiguration은 Spring ApplicationContext에서 사용 가능하고 (Ordered), DispatcherServlet에 의해 사용되는 하나 이상의 MessageSource 인스턴스를 반복하는 CompositeMessageSource 개념을 가지고있는 것처럼 보입니다. 이렇게하면 자동 구성에서 MessageSource를 선언함으로써 모든 시작자가 사용 가능한 메시지에 기여할 수 있습니다.

내가 부탁하는 것을 할 수 있습니까? 앱 개발자에게 가장 손을 떼는 솔루션은 무엇입니까?

해결법

  1. ==============================

    1.어쩌면 그것은 길지만 당신은 BeanFactoryPostProcessor를 사용해 볼 수 있습니다.

    어쩌면 그것은 길지만 당신은 BeanFactoryPostProcessor를 사용해 볼 수 있습니다.

    아이디어는 다음과 같습니다.

    그러나 더 나은 방법이있을 수 있습니다.

  2. ==============================

    2.나는 이것을 다음과 같이 설정했다. 현재 en_US 만 지원하고 있지만 국제화 (i18n)를 사용하여 여러 언어를 처리하도록 설정되어 있습니다.

    나는 이것을 다음과 같이 설정했다. 현재 en_US 만 지원하고 있지만 국제화 (i18n)를 사용하여 여러 언어를 처리하도록 설정되어 있습니다.

    코드 요지보기 : github 요지 코드

    이 빈을 Application.java에 추가하여 기본 로케일을 설정하고 메시지 소품의 위치를 ​​구성하십시오.

    서비스는 세션에서 기본 로케일을 가져온 다음 소품에서 메시지 텍스트를 가져옵니다.

    메시지 svc를 주입 한 다음 id를 전달하여 props 파일에서 값을 가져옵니다.

    이동 / 리소스 :

    이 주제에 대한보다 자세한 기사는 다음에서 볼 수 있습니다. 메시지 등록 정보를 사용한 Spring Boot 국제화 i18n

    코드 요지보기 : github gist의 코드

  3. ==============================

    3.나는 이것이 늙고 대답하는 질문이라는 것을 알지만, 다른 날에 같은 문제를 겪었고 그것을 해결하기로 결정한 블로그 게시물을 썼다. 이 스레드에서 내 솔루션에 대한 영감을 얻은 이후로 여기에서 공유해야한다고 생각했습니다.

    나는 이것이 늙고 대답하는 질문이라는 것을 알지만, 다른 날에 같은 문제를 겪었고 그것을 해결하기로 결정한 블로그 게시물을 썼다. 이 스레드에서 내 솔루션에 대한 영감을 얻은 이후로 여기에서 공유해야한다고 생각했습니다.

    즉, MessageSource 빈 생성을 가로 채기위한 sodik의 아이디어가 필요하지만 BeanFactoryPostProcessor를 사용하는 대신 BeanPostProcessor를 사용하고 응용 프로그램 컨텍스트에서 원래 MessageSource를 바꾸는 대신 자신의 부모로 추가합니다.

    @Bean
    BeanPostProcessor messageSourceCustomExtender() {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                return bean;
            }
    
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof HierarchicalMessageSource && beanName.equals("messageSource")) {
                    ResourceBundleMessageSource parent = new ResourceBundleMessageSource();
                    parent.setBasename("custom");
    
                    ((HierarchicalMessageSource) bean).setParentMessageSource(parent);
                }
    
                return bean;
            }
        };
    }
    

    내 솔루션에 대한 몇 가지주의 사항을 설명하는 전체 블로그 게시물을 읽을 수 있습니다. http://www.thomaskasene.com/2016/08/20/custom-spring-boot-starter-messagesource/

    약간의 수정을 한 후에, 원래의 MessageSource 빈이 너무 일찍 생성되어 애플리케이션 속성 (가장 중요한 것은 spring.messages.basename)을 무시하게되므로 BeanFactoryPostProcessor를 사용하는 것이 잘못되었다는 것을 깨달았다. 이는 응용 프로그램이 이러한 속성을 구성 할 수 없음을 의미합니다. 아래의 BeanFactoryPostProcessor 문서에서 발췌 한 내용을 참조하십시오.

    대신 BeanPostProcessor를 사용하도록 위의 예제를 업데이트했습니다. BeanPostProcessor는 Bean 정의가 아닌 Bean 인스턴스를 변경합니다.

  4. from https://stackoverflow.com/questions/28750292/custom-spring-boot-starter-how-do-you-contribute-i18n-messages-to-the-messageso by cc-by-sa and MIT license