001/* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020package org.sonar.api.utils; 021 022import com.google.common.collect.Iterators; 023import com.google.common.collect.Lists; 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027import java.util.*; 028 029public class LocalizedMessages extends ResourceBundle { 030 031 private static final Logger LOG = LoggerFactory.getLogger(LocalizedMessages.class); 032 033 private Locale locale; 034 private List<ResourceBundle> bundles; 035 036 /** 037 * Constructs a resource bundle from a list of other resource bundles. If 038 * there are duplicate keys, the key from the resource bundle with the 039 * smallest index takes precedence. 040 */ 041 public LocalizedMessages(Locale locale, String... basenames) { 042 this.locale = locale; 043 bundles = new ArrayList<ResourceBundle>(basenames.length); 044 for (String basename : basenames) { 045 bundles.add(getBundle("sonar.bundles." + basename, locale)); 046 } 047 } 048 049 @Override 050 public Locale getLocale() { 051 return locale; 052 } 053 054 public String format(String key, Object... args) { 055 return format(true, key, args); 056 } 057 058 public String formatQuietly(String key, Object... args) { 059 return format(false, key, args); 060 } 061 062 private String format(boolean logIfMissing, String key, Object... args) { 063 try { 064 String message = getString(key); 065 return String.format(locale, message, args); 066 067 } catch (MissingResourceException e) { 068 if (logIfMissing) { 069 LOG.warn("Missing translation: key==" + key + ",locale=" + locale); 070 } 071 return key; 072 } 073 } 074 075 /* 076 * (non-Javadoc) 077 * 078 * @see java.util.ResourceBundle#getKeys() 079 */ 080 081 @Override 082 public Enumeration<String> getKeys() { 083 return new Enumeration<String>() { 084 private Set<String> keys = new HashSet<String>(); 085 086 // Set iterator to simulate enumeration 087 private Iterator<String> i; 088 089 // Constructor 090 { 091 for (ResourceBundle b : bundles) { 092 keys.addAll(Lists.newArrayList(Iterators.forEnumeration(b.getKeys()))); 093 } 094 i = keys.iterator(); 095 } 096 097 public boolean hasMoreElements() { 098 return i.hasNext(); 099 } 100 101 public String nextElement() { 102 return i.next(); 103 } 104 }; 105 } 106 107 /* 108 * (non-Javadoc) 109 * 110 * @see java.util.ResourceBundle#handleGetObject(java.lang.String) 111 */ 112 113 @Override 114 protected Object handleGetObject(String key) { 115 for (ResourceBundle b : bundles) { 116 try { 117 return b.getObject(key); 118 } catch (MissingResourceException mre) { 119 // iterate 120 } 121 } 122 throw new MissingResourceException(null, null, key); 123 } 124}