2010-04-09 4 views
14

로그 또는 지원 담당자에게 문의하는 문장에서부터 회사 또는 제품 이름이 포함 된 브랜딩 같은 문자열에 이르기까지 동일한 하위 문자열이 포함 된 많은 문자열이있었습니다. 반복은 우리 자신을 위해 몇 가지 문제 (주로 오타 또는 복사/붙여 넣기 오류)를 일으키고 있었지만 번역사가 번역해야하는 텍스트 양이 증가한다는 문제가 있습니다.Java ResourceBundle 문자열에서 반복을 피하려면 어떻게합니까?

내가 생각 해낸 해결책은 다음과 같이 갔다 : 실제 자원 번들에

public class ExpandingResourceBundleControl extends ResourceBundle.Control { 
    public static final ResourceBundle.Control EXPANDING = 
    new ExpandingResourceBundleControl(); 

    private ExpandingResourceBundleControl() { } 

    @Override 
    public ResourceBundle newBundle(String baseName, Locale locale, String format, 
            ClassLoader loader, boolean reload) 
    throws IllegalAccessException, InstantiationException, IOException { 

     ResourceBundle inner = super.newBundle(baseName, locale, format, loader, reload); 
     return inner == null ? null : new ExpandingResourceBundle(inner, loader); 
    } 
} 

ExpandingResourceBundle 대표를하지만 {{this.kind.of.thing}}에서 키를 조회 할의 변환을 수행 자원.

당신이 이들 중 하나를 얻을 할 때마다, 당신은 가야 :

ResourceBundle.getBundle("com/acme/app/Bundle", EXPANDING); 

을 그리고이 잘 작동합니다 - 잠시 동안.

결국 어떤 새로운 코드 (우리의 경우 Matisse에서 자동 생성 된 코드)는 사용자 정의 컨트롤을 지정하지 않고 동일한 리소스 번들을 찾습니다. 이것은 함께 호출 한 후 간단한 호출을 수행하는 간단한 단위 테스트를 작성하면 재현 할 수없는 것처럼 보입니다. 그러나 응용 프로그램이 실제로 실행될 때 발생합니다. 아무래도 ResourceBundle 내부의 캐시가 좋은 값을 내보내고 깨진 값으로 바꿉니다. 이유와 Sun의 jar 파일이 디버그 정보없이 컴파일 되었기 때문에 디버깅 정보가 필요하지 않은지 아직 알지 못합니다.

내 질문 :

  1. 세계적으로 내가 인식하지 않을 수 있습니다 기본 같은, ResourceBundle.Control를 설정하는 몇 가지 방법이 있나요? 그것은 모든 것을 다소 우아하게 해결할 것입니다.

  2. ResourceBundle 클래스를 전혀 변경하지 않고도 이런 종류의 것을 우아하게 처리 할 수있는 다른 방법이 있습니까?

+0

자바가 가지고 있다면 그것은 메타 프로그래밍을 사용하여 쉽게 처리 할 수 ​​있습니다. –

답변

6

이것이 ResourceBundles가 작동하도록 설계된 기본적인 결함입니다. 다른 키를 참조하는 키는 DRY (자동 반복 안 함) 원칙을 자동 위반합니다. 이 문제를 해결하는 방법은 메서드와 비슷합니다. EL 표기법을 사용하여 메시지에서 리소스 키를 지정할 수있는 ReflectiveResourceBundle 클래스를 만듭니다.

잘못된 방법 :

my.name.first=Bob 
my.name.last=Smith 
my.name.full=Bob Smith 

올바른 방법 :

my.name.first=Bob 
my.name.last=Smith 
my.name.full=${my.name.first} ${my.name.last} 

내가 그렇게 당신이나 다른 사람이 다운로드 할 수 있습니다 uploaded the code to GitHub했습니다. 또한, Stripes Framework (http://www.stripesframework.org/)를 사용하는 모든 사용자를 위해 몇 가지 샘플 코드를 추가하여 신속하게 작동하도록했습니다.

이것을 표준 JSTL fmt taglibs와 함께 사용하는 트릭은 HttpServletRequest의 리소스를 우리 자신의 것으로 대체 한 인터셉터를 설정하는 것이 었습니다. 코드는 다음과 같습니다.

ResourceBundle bundle = MyStaticResourceHoldingTheBundle.getBundle(); 
Config.set(request, Config.FMT_LOCALIZATION_CONTEXT, new LocalizationContext(bundle, locale)); 

자세한 내용은 위 링크의 stripes.interceptor 패키지를 살펴보십시오.

+0

맞습니다. 이것은 우리 솔루션과 매우 유사하며 ResourceBundle.getBundle()을 사용하여 생성 된 코드가 대안을받지 못하는 동일한 단점이 있습니다. 가장 큰 차이점은 우리의 경우 우리는 기존의 ResourceBundle 캐시를 사용하는 반면, 여러분의 경우에는 캐시를 별도로 유지해야한다는 것입니다. 아마도 캐시 된 번들을 가끔씩 썬의 캐시에서 처리해야 할 수도 있습니다. – Trejkaz

+0

나는 단지 우연히 같은 문제에 걸려 넘어 졌기 때문에 : 기본적으로 나는 ResourceBundle의 모든 기능을 재사용하고 싶지만 키 확장을 추가하고 싶다. 그래서 PropertyResourceBundle에서 파생되고 그에 따라 handleGetObject()가 오버로드됩니다 (Matt Brocks 소스에서 볼 수 있듯이). 그런 다음 ResourceBundle.Control에서 파생 된 newBundle()을 오버라이드하여 사용자 정의 PropertyResourceBundle (이 메서드의 원래 소스를 수정 한)을 반환하고 ResourceBundle.getBundle()에 전달했습니다. 이렇게하면 ResourceBundle의 모든 기능을 재사용하고 키 확장을 추가 할 수 있습니다. – quaylar

+0

@Matt Brock, 링크가 끊어진 것 같습니다. 페이지를 공유 할 수 있습니까? –

0

문자열의 반복은 당신이 특정 문자열이 공유 리소스 번들 디자인 악몽이되지 않도록하지만 같은 프로젝트 내에서 반복 될 것이다라는 것을 알고 의미에서 지역화 된 경우에, 당신은 아래로 문자열을 깨는 고려해 볼 수 있습니다 여러 키 - 값 부분으로. 반복되는 부분은 반복하지 말고 반복하고 반복 된 부분은 다시 사용하십시오. 예를 들어, 당신이 표시해야 다음 두 문자열이 있다고 할 수 있습니다 ". 레드 덮인 로빈 호주에 작은 참새목 조류 기본입니다"

  1. 는 "레드 덮인 로빈이에서 발견된다 대륙의 많은 지역을 가로 지르는 건조기 지역. "

다음과 같이 자원 번들이있을 수 :

robin.name=The Red-capped Robin 
robin.native=is a small passerine bird native to Australia. 
robin.region=is found in dryer regions across much of the continent. 

을 한 다음 비록에 대해주의해야 bundle.getString("robin.name")+bundle.getString(robin.native).

한 가지를 필요로 필요한 부품을 결합하여 그 주제와 같은 문법 규칙 술어 순서 등은 모든 언어에서 동일하지 않을 수 있습니다. 따라서 문장을 분할 할 때는 조심해야합니다.

+5

실제로 이것은 다른 컨텍스트 (예 : 메뉴 또는 상태 표시 줄), 주제의 성별 및 복수 (1, 2, 27 등)도 문화에 따라 바뀌기 때문에 나쁜 생각입니다. – devstuff

+0

이것은 실제로 우리가 ResourceBundle 측에서 모든 삽입 작업을 수행하는 정확한 이유입니다. 우리의 현재 접근 방식에서는 {{robin.name}}을 그 아래 값의 적절한 위치에 놓음으로써 예제가 수행됩니다. 누군가가 작동하지 않는 언어를 만난다면 변수를 완전히 제거 할 권한이 있습니다. 그러나 ... 우리의 솔루션은 당연히 올바르게 작동하는 것이 까다로울 수 있습니다. – Trejkaz

관련 문제