001/* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2014 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * SonarQube 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 * SonarQube 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 License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020package org.sonar.api.utils; 021 022import com.google.common.collect.Iterators; 023import com.google.common.collect.Lists; 024import org.sonar.api.utils.log.Logger; 025import org.sonar.api.utils.log.Loggers; 026 027import java.util.ArrayList; 028import java.util.Enumeration; 029import java.util.HashSet; 030import java.util.Iterator; 031import java.util.List; 032import java.util.Locale; 033import java.util.MissingResourceException; 034import java.util.ResourceBundle; 035import java.util.Set; 036 037public class LocalizedMessages extends ResourceBundle { 038 039 private static final Logger LOG = Loggers.get(LocalizedMessages.class); 040 041 private Locale locale; 042 private List<ResourceBundle> bundles; 043 044 /** 045 * Constructs a resource bundle from a list of other resource bundles. If 046 * there are duplicate keys, the key from the resource bundle with the 047 * smallest index takes precedence. 048 */ 049 public LocalizedMessages(Locale locale, String... basenames) { 050 this.locale = locale; 051 bundles = new ArrayList<ResourceBundle>(basenames.length); 052 for (String basename : basenames) { 053 bundles.add(getBundle("sonar.bundles." + basename, locale)); 054 } 055 } 056 057 @Override 058 public Locale getLocale() { 059 return locale; 060 } 061 062 public String format(String key, Object... args) { 063 return format(true, key, args); 064 } 065 066 public String formatQuietly(String key, Object... args) { 067 return format(false, key, args); 068 } 069 070 private String format(boolean logIfMissing, String key, Object... args) { 071 try { 072 String message = getString(key); 073 return String.format(locale, message, args); 074 075 } catch (MissingResourceException e) { 076 if (logIfMissing) { 077 LOG.warn("Missing translation: key==" + key + ",locale=" + locale); 078 } 079 return key; 080 } 081 } 082 083 /* 084 * (non-Javadoc) 085 * 086 * @see java.util.ResourceBundle#getKeys() 087 */ 088 @Override 089 public Enumeration<String> getKeys() { 090 return new KeyEnumeration(); 091 } 092 093 /* 094 * (non-Javadoc) 095 * 096 * @see java.util.ResourceBundle#handleGetObject(java.lang.String) 097 */ 098 @Override 099 protected Object handleGetObject(String key) { 100 for (ResourceBundle b : bundles) { 101 try { 102 return b.getObject(key); 103 } catch (MissingResourceException mre) { 104 // iterate 105 } 106 } 107 throw new MissingResourceException(null, null, key); 108 } 109 110 private class KeyEnumeration implements Enumeration<String> { 111 private Set<String> keys = new HashSet<String>(); 112 113 // Set iterator to simulate enumeration 114 private Iterator<String> i; 115 116 // Constructor 117 { 118 for (ResourceBundle b : bundles) { 119 keys.addAll(Lists.newArrayList(Iterators.forEnumeration(b.getKeys()))); 120 } 121 i = keys.iterator(); 122 } 123 124 @Override 125 public boolean hasMoreElements() { 126 return i.hasNext(); 127 } 128 129 @Override 130 public String nextElement() { 131 return i.next(); 132 } 133 } 134}