In Java/Spring, how to gracefully handle missing translation values?

前端 未结 2 1782
深忆病人
深忆病人 2021-01-18 09:16

I\'m using Java + Spring for an international website.

The 2 languages are ZH and EN (Chinese and English).

I have 2 files: messages.properties (for English

相关标签:
2条回答
  • 2021-01-18 10:00

    You could create your own Custom MessageSource for this purpose.

    Something like:

    public class SpecialMessageSource extends ReloadableResourceBundleMessageSource {
    
          @Override
          protected MessageFormat resolveCode(String code, Locale locale) {
             MessageFormat result = super.resolveCode(code, locale);
             if (result.getPattern().isEmpty() && locale == Locale.CHINESE) {
                return super.resolveCode(code, Locale.ENGLISH);
             }
             return result;
          }
    
          @Override
          protected String resolveCodeWithoutArguments(String code, Locale locale) {
             String result= super.resolveCodeWithoutArguments(code, locale);
             if ((result == null || result.isEmpty()) && locale == Locale.CHINESE) {
                return super.resolveCodeWithoutArguments(code, Locale.ENGLISH);
             }
             return result;
          }
       }
    

    and configure this messageSource bean in spring xml as

    <bean id="messageSource" class="SpecialMessageSource">
    .....
    </bean>
    

    Now to get resolved Label you will be invoking MessageSource's either of the below methods

    String getMessage(String code, Object[] args, Locale locale);
    String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
    

    resolveCode() will be called when your message label has arguments and you pass those arguments via args parameter like below
    invalid.number= {0} is Invalid
    and you invoke messageSource.getMessage("INVALID_NUMBER", new Object[]{2d}, locale)

    resolveCodeWithoutArguments() will be called when your message label does not have arguments and you pass args parameter as null
    validation.success = Validation Success
    and you invoke messageSource.getMessage("INVALID_NUMBER", null, locale)

    0 讨论(0)
  • 2021-01-18 10:02

    @harrybvp's answer got me on the right track. This is the code that seems to work for me (and is unit-testable when you mock the methods that call "super"):

        public class GracefulMessageSource extends org.springframework.context.support.ReloadableResourceBundleMessageSource {
    
            final static private Locale defaultLocale = Locale.ENGLISH;
    
            @Override protected MessageFormat resolveCode(final String code, final Locale locale) {
                MessageFormat result = superResolveCode(code, locale);
    
                if (result.toPattern().isEmpty() && !locale.equals(this.defaultLocale)) {
                    result = superResolveCode(code, this.defaultLocale);
                }
    
                return result;
            }
    
            @Override protected String resolveCodeWithoutArguments(final String code, final Locale locale) {
                String result = superResolveCodeWithoutArguments(code, locale);
    
                if (result.isEmpty() && !locale.equals(this.defaultLocale)) {
                    result = superResolveCodeWithoutArguments(code, this.defaultLocale);
                }
    
                return result;
            }
    
            protected MessageFormat superResolveCode(final String code, final Locale locale) {
                return super.resolveCode(code, locale);
    
            }
    
            protected String superResolveCodeWithoutArguments(final String code, final Locale locale) {
                return super.resolveCodeWithoutArguments(code, locale);
    
            }
    
        }
    

    and in my webmvc-config.xml:

    <bean id="messageSource" class="com.mycode.fe.web.GracefulMessageSource">
        <property name="basename">
            <value>${content.path.config}/WEB-INF/messages</value>
        </property>
        <property name="defaultEncoding" value="UTF-8" />
        <property name="cacheSeconds" value="2"/>
        <property name="fallbackToSystemLocale" value="true"/>
    </bean>
    

    Then in my Velocity view templates:

    For a normal key with no arguments: #springMessage('menu_item1')

    For a key that accepts arguments: #springMessageText('male_to_female_ratio' [3, 2])

    Then in the messages.properties (English translations): male_to_female_ratio = There is a {0}:{1} male-to-female ratio.

    0 讨论(0)
提交回复
热议问题