2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.knx.internal.i18n;
15 import java.text.MessageFormat;
16 import java.util.Locale;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.core.i18n.LocaleProvider;
21 import org.openhab.core.i18n.TranslationProvider;
22 import org.osgi.framework.Bundle;
23 import org.osgi.framework.FrameworkUtil;
26 * This class provides translations. It is a helper class for i18n / localization efforts.
28 * @implNote It is implemented as a static singleton, enforced by the single-element enum pattern.
29 * @apiNote {@link #setProvider(LocaleProvider, TranslationProvider)} must be called to provide tanslation service,
30 * otherwise all functions will return untranslated text.
31 * Thread safety is ensured.
32 * @author Holger Friedrich - Initial contribution
36 public enum KNXTranslationProvider {
39 private @Nullable LocaleProvider localeProvider;
40 private @Nullable TranslationProvider translationProvider;
41 private Bundle bundle;
43 private KNXTranslationProvider() {
44 localeProvider = null;
45 translationProvider = null;
46 bundle = FrameworkUtil.getBundle(this.getClass());
52 * @param text text to be translated, may contain placeholders \{n\} for the n-th optional argument of this function
53 * @param arguments any optional arguments, will be inserted
54 * @return translated text with substitutions if translationProvider is set and provides a translation, otherwise
55 * returns original text with substitutions
57 public String get(final String text, @Nullable Object @Nullable... arguments) {
58 // ensure thread safety: calls to setProvider(..) should not lead to race condition
59 final TranslationProvider translationProvider = this.translationProvider;
60 final LocaleProvider localeProvider = this.localeProvider;
61 if (translationProvider != null) {
62 // localeProvider might be null, but if not, getLocale will return NonNull Locale
63 // locale cannot be cached, as getLocale() will return different result once locale is changed by user
64 final Locale locale = (localeProvider != null) ? localeProvider.getLocale() : Locale.getDefault();
65 final String res = translationProvider.getText(bundle, text, text, locale, arguments);
70 // translating not possible, we still have the original text without any subsititutions
71 if (arguments == null || arguments.length == 0) {
74 // else execute pattern substitution in untranslated text
75 return MessageFormat.format(text, arguments);
79 * get exception in user readable (and possibly localized) form
81 * @param e any exception
82 * @return localized message in form [description (translated)] [class name], [e.getLocalizedMessage (not
83 * translated)]), empty string for null. May possibly change in further releases.
85 public String getLocalizedException(final Throwable e) {
86 StringBuilder res = new StringBuilder();
87 final String exName = e.getClass().getSimpleName();
88 final String key = "exception." + exName;
89 final String translatedDescription = KNXTranslationProvider.I18N.get(key);
90 Boolean foundTranslation = !key.equals(translatedDescription);
91 // detailed message cannot be translated, e.getLocalizedMessage will likely return English
92 String detail = e.getLocalizedMessage();
97 if (foundTranslation) {
98 res.append(translatedDescription);
101 if (!detail.isBlank()) {
108 if (!detail.isBlank()) {
113 return res.toString();
117 * Set translation providers. To be called to make any translation work.
119 * @param localeProvider openHAB locale provider, can be generated via {@literal @}Activate / {@literal @}Reference
120 * LocaleProvider in handler factory
121 * @param translationProvider openHAB locale provider, can be generated via {@literal @}Activate /
122 * {@literal @}Reference TranslationProvider in handler factory
124 public void setProvider(@Nullable LocaleProvider localeProvider,
125 @Nullable TranslationProvider translationProvider) {
126 this.localeProvider = localeProvider;
127 this.translationProvider = translationProvider;