001/* 002 * SonarQube 003 * Copyright (C) 2009-2017 SonarSource SA 004 * mailto:info AT sonarsource DOT com 005 * 006 * This program 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 * This program 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 java.util.ArrayList; 023import java.util.Enumeration; 024import java.util.HashSet; 025import java.util.Iterator; 026import java.util.List; 027import java.util.Locale; 028import java.util.MissingResourceException; 029import java.util.ResourceBundle; 030import java.util.Set; 031import org.sonar.api.utils.log.Logger; 032import org.sonar.api.utils.log.Loggers; 033 034public class LocalizedMessages extends ResourceBundle { 035 036 private static final Logger LOG = Loggers.get(LocalizedMessages.class); 037 038 private Locale locale; 039 private List<ResourceBundle> bundles; 040 041 /** 042 * Constructs a resource bundle from a list of other resource bundles. If 043 * there are duplicate keys, the key from the resource bundle with the 044 * smallest index takes precedence. 045 */ 046 public LocalizedMessages(Locale locale, String... basenames) { 047 this.locale = locale; 048 bundles = new ArrayList<>(basenames.length); 049 for (String basename : basenames) { 050 bundles.add(getBundle("sonar.bundles." + basename, locale)); 051 } 052 } 053 054 @Override 055 public Locale getLocale() { 056 return locale; 057 } 058 059 public String format(String key, Object... args) { 060 return format(true, key, args); 061 } 062 063 public String formatQuietly(String key, Object... args) { 064 return format(false, key, args); 065 } 066 067 private String format(boolean logIfMissing, String key, Object... args) { 068 try { 069 String message = getString(key); 070 return String.format(locale, message, args); 071 072 } catch (MissingResourceException e) { 073 if (logIfMissing) { 074 LOG.warn("Missing translation: key==" + key + ",locale=" + locale); 075 } 076 return key; 077 } 078 } 079 080 /* 081 * (non-Javadoc) 082 * 083 * @see java.util.ResourceBundle#getKeys() 084 */ 085 @Override 086 public Enumeration<String> getKeys() { 087 return new KeyEnumeration(); 088 } 089 090 /* 091 * (non-Javadoc) 092 * 093 * @see java.util.ResourceBundle#handleGetObject(java.lang.String) 094 */ 095 @Override 096 protected Object handleGetObject(String key) { 097 for (ResourceBundle b : bundles) { 098 try { 099 return b.getObject(key); 100 } catch (MissingResourceException mre) { 101 // iterate 102 } 103 } 104 throw new MissingResourceException(null, null, key); 105 } 106 107 private class KeyEnumeration implements Enumeration<String> { 108 private Set<String> keys = new HashSet<>(); 109 110 // Set iterator to simulate enumeration 111 private Iterator<String> i; 112 113 // Constructor 114 { 115 for (ResourceBundle b : bundles) { 116 Enumeration<String> bundleKeys = b.getKeys(); 117 while (bundleKeys.hasMoreElements()) { 118 keys.add(bundleKeys.nextElement()); 119 } 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}