introduce DynamicBundle and LanguageBundle EP

language bundle allows to load localized resources via plugin machinery

GitOrigin-RevId: c2dca049a840b7c0b79ac372f42631bd0e496a83
This commit is contained in:
Sergey Ignatov
2019-12-17 09:02:33 +00:00
committed by intellij-monorepo-bot
parent 39e386b097
commit 11178787f7
29 changed files with 116 additions and 50 deletions
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.PropertyKey;
/**
* @author max
*/
public class JavaErrorMessages extends AbstractBundle {
public class JavaErrorMessages extends DynamicBundle {
@NotNull
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
@@ -15,11 +15,11 @@
*/
package org.jetbrains.lang.manifest;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class ManifestBundle extends AbstractBundle {
public class ManifestBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return BUNDLE.getMessage(key, params);
@@ -1,12 +1,12 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.analysis;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class JvmAnalysisBundle extends AbstractBundle {
public class JvmAnalysisBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return ourInstance.getMessage(key, params);
}
@@ -1,8 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.intention;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.DynamicBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.CustomLoadingExtensionPointBean;
import com.intellij.util.containers.ContainerUtil;
@@ -47,7 +47,7 @@ public final class IntentionActionBean extends CustomLoadingExtensionPointBean<I
return null;
}
final ResourceBundle bundle = AbstractBundle.getResourceBundle(baseName, getLoaderForClass());
final ResourceBundle bundle = DynamicBundle.INSTANCE.getResourceBundle(baseName, getLoaderForClass());
final String[] keys = categoryKey.split("/");
if (keys.length > 1) {
@@ -1,8 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.DynamicBundle;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.diagnostic.PluginException;
import com.intellij.lang.Language;
@@ -189,7 +189,7 @@ public class InspectionEP extends LanguageExtensionPoint<InspectionProfileEntry>
}
return null;
}
ResourceBundle resourceBundle = AbstractBundle.getResourceBundle(baseName, getLoaderForClass());
ResourceBundle resourceBundle = DynamicBundle.INSTANCE.getResourceBundle(baseName, getLoaderForClass());
return CommonBundle.message(resourceBundle, key);
}
@@ -1,8 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.configurationStore
import com.intellij.AbstractBundle
import com.intellij.CommonBundle
import com.intellij.DynamicBundle
import com.intellij.configurationStore.schemeManager.ROOT_CONFIG
import com.intellij.configurationStore.schemeManager.SchemeManagerFactoryBase
import com.intellij.ide.IdeBundle
@@ -293,7 +293,7 @@ private fun getComponentPresentableName(state: State, aClass: Class<*>, pluginDe
private fun messageOrDefault(classLoader: ClassLoader, bundleName: String, defaultName: String): String {
try {
return CommonBundle.messageOrDefault(
AbstractBundle.getResourceBundle(bundleName, classLoader), "exportable.$defaultName.presentable.name", defaultName)
DynamicBundle.INSTANCE.getResourceBundle(bundleName, classLoader), "exportable.$defaultName.presentable.name", defaultName)
}
catch (e: MissingResourceException) {
LOG.warn("Missing bundle ${bundleName} at ${classLoader}: ${e.message}")
@@ -1,5 +1,6 @@
<idea-plugin>
<extensionPoints>
<extensionPoint name="languageBundle" beanClass="com.intellij.DynamicBundle$LanguageBundleEP"/>
<!--suppress PluginXmlValidity -->
<extensionPoint name="applicationService" beanClass="com.intellij.openapi.components.ServiceDescriptor" dynamic="true"/>
<!--suppress PluginXmlValidity -->
@@ -0,0 +1,57 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
import java.util.ResourceBundle;
public abstract class DynamicBundle extends AbstractBundle {
private final static Logger LOG = Logger.getInstance(DynamicBundle.class);
private final static Method SET_PARENT = ReflectionUtil.getDeclaredMethod(ResourceBundle.class, "setParent", ResourceBundle.class);
protected DynamicBundle(@NotNull String pathToBundle) {
super(pathToBundle);
}
@Override
protected ResourceBundle findBundle(@NotNull String pathToBundle,
@NotNull ClassLoader baseLoader,
@NotNull ResourceBundle.Control control) {
ResourceBundle base = super.findBundle(pathToBundle, baseLoader, control);
LanguageBundleEP langBundle = findLanguageBundle();
if (langBundle == null) return base;
ResourceBundle pluginBundle = super.findBundle(pathToBundle, langBundle.getLoaderForClass(), control);
if (pluginBundle == null) return base;
try {
if (SET_PARENT != null) {
SET_PARENT.invoke(pluginBundle, base);
}
}
catch (Exception e) {
LOG.warn(e);
}
return pluginBundle;
}
// todo: one language per application
private static LanguageBundleEP findLanguageBundle() {
return LanguageBundleEP.EP_NAME.findExtension(LanguageBundleEP.class);
}
public static final DynamicBundle INSTANCE = new DynamicBundle("") {
};
public static class LanguageBundleEP extends AbstractExtensionPointBean {
public static final ExtensionPointName<LanguageBundleEP> EP_NAME = ExtensionPointName.create("com.intellij.languageBundle");
}
}
@@ -15,14 +15,14 @@
*/
package com.intellij.ide;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author yole
*/
public class IdeBundle extends AbstractBundle {
public class IdeBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return INSTANCE.getMessage(key, params);
}
@@ -16,7 +16,7 @@
package com.intellij.openapi.vfs;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.PropertyKey;
/**
* @author yole
*/
public class VfsBundle extends AbstractBundle {
public class VfsBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return ourInstance.getMessage(key, params);
@@ -1,8 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.DynamicBundle;
import com.intellij.diagnostic.PluginException;
import com.intellij.openapi.components.ComponentConfig;
import com.intellij.openapi.components.ComponentManager;
@@ -642,7 +642,7 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor, Plu
ResourceBundle bundle = null;
if (myResourceBundleBaseName != null) {
try {
bundle = AbstractBundle.getResourceBundle(myResourceBundleBaseName, getPluginClassLoader());
bundle = DynamicBundle.INSTANCE.getResourceBundle(myResourceBundleBaseName, getPluginClassLoader());
}
catch (MissingResourceException e) {
LOG.info("Cannot find plugin " + myId + " resource-bundle: " + myResourceBundleBaseName);
@@ -15,14 +15,14 @@
*/
package com.intellij.openapi.externalSystem.util;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author Denis Zhdanov
*/
public class ExternalSystemBundle extends AbstractBundle {
public class ExternalSystemBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return BUNDLE.getMessage(key, params);
@@ -2,13 +2,14 @@
package com.intellij.execution;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author lesya
*/
public class ExecutionBundle extends AbstractBundle {
public class ExecutionBundle extends DynamicBundle {
@NotNull
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return ourInstance.getMessage(key, params);
@@ -1,7 +1,7 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.template.impl;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import com.intellij.codeInsight.template.Macro;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateContextType;
@@ -640,7 +640,7 @@ public final class TemplateSettings implements PersistentStateComponent<Template
String key = element.getAttributeValue(KEY);
String id = element.getAttributeValue(ID);
if (resourceBundle != null && key != null) {
ResourceBundle bundle = AbstractBundle.getResourceBundle(resourceBundle, classLoader);
ResourceBundle bundle = DynamicBundle.INSTANCE.getResourceBundle(resourceBundle, classLoader);
description = bundle.getString(key);
}
else {
@@ -15,11 +15,11 @@
*/
package com.intellij.history.integration;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class LocalHistoryBundle extends AbstractBundle {
public class LocalHistoryBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return INSTANCE.getMessage(key, params);
}
@@ -1,7 +1,7 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.NullableLazyValue;
@@ -42,7 +42,7 @@ public class TypeNameEP extends AbstractExtensionPointBean {
bundleName = myPluginDescriptor.getResourceBundleBaseName();
}
if (bundleName != null) {
ResourceBundle bundle = AbstractBundle.getResourceBundle(bundleName, getLoaderForClass());
ResourceBundle bundle = DynamicBundle.INSTANCE.getResourceBundle(bundleName, getLoaderForClass());
return bundle.getString(resourceKey);
}
}
@@ -1,8 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.options;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.DynamicBundle;
import com.intellij.diagnostic.PluginException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ComponentManager;
@@ -82,7 +82,7 @@ public class ConfigurableEP<T extends UnnamedConfigurable> extends AbstractExten
String pathToBundle = findPathToBundle();
if (pathToBundle == null) return null; // a path to bundle is not specified or cannot be found
ClassLoader loader = myPluginDescriptor == null ? null : myPluginDescriptor.getPluginClassLoader();
return AbstractBundle.getResourceBundle(pathToBundle, loader != null ? loader : getClass().getClassLoader());
return DynamicBundle.INSTANCE.getResourceBundle(pathToBundle, loader != null ? loader : getClass().getClassLoader());
}
@Nullable
@@ -15,14 +15,14 @@
*/
package com.intellij.internal.statistic;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author Denis Zhdanov
*/
public class StatisticsBundle extends AbstractBundle {
public class StatisticsBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return BUNDLE.getMessage(key, params);
@@ -1,8 +1,8 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.actionSystem.impl;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.DynamicBundle;
import com.intellij.diagnostic.PluginException;
import com.intellij.diagnostic.StartUpMeasurer;
import com.intellij.icons.AllIcons;
@@ -233,7 +233,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Disposab
private static ResourceBundle getActionsResourceBundle(@NotNull IdeaPluginDescriptor plugin) {
String resBundleName = PluginManagerCore.CORE_ID != plugin.getPluginId()
? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE;
return resBundleName == null ? null : AbstractBundle.getResourceBundle(resBundleName, plugin.getPluginClassLoader());
return resBundleName == null ? null : DynamicBundle.INSTANCE.getResourceBundle(resBundleName, plugin.getPluginClassLoader());
}
private static boolean isSecondary(Element element) {
@@ -56,13 +56,13 @@ public abstract class AbstractBundle {
private static final Map<ClassLoader, Map<String, ResourceBundle>> ourCache =
ConcurrentFactoryMap.createWeakMap(k -> ContainerUtil.createConcurrentSoftValueMap());
public static ResourceBundle getResourceBundle(@NotNull String pathToBundle, @NotNull ClassLoader loader) {
public ResourceBundle getResourceBundle(@NotNull String pathToBundle, @NotNull ClassLoader loader) {
Map<String, ResourceBundle> map = ourCache.get(loader);
ResourceBundle result = map.get(pathToBundle);
if (result == null) {
try {
ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_PROPERTIES);
result = ResourceBundle.getBundle(pathToBundle, Locale.getDefault(), loader, control);
result = findBundle(pathToBundle, loader, control);
}
catch (MissingResourceException e) {
LOG.info("Cannot load resource bundle from *.properties file, falling back to slow class loading: " + pathToBundle);
@@ -73,4 +73,8 @@ public abstract class AbstractBundle {
}
return result;
}
protected ResourceBundle findBundle(@NotNull String pathToBundle, @NotNull ClassLoader loader, @NotNull ResourceBundle.Control control) {
return ResourceBundle.getBundle(pathToBundle, Locale.getDefault(), loader, control);
}
}
@@ -1,12 +1,12 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.intellij.plugins.intelliLang
import com.intellij.AbstractBundle
import com.intellij.DynamicBundle
import org.jetbrains.annotations.PropertyKey
private const val BUNDLE = "org.intellij.plugins.intelliLang.IntelliLangBundle"
object IntelliLangBundle : AbstractBundle(BUNDLE) {
object IntelliLangBundle : DynamicBundle(BUNDLE) {
@JvmStatic
fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
}
@@ -15,12 +15,12 @@
*/
package org.jetbrains.idea.devkit;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class DevKitBundle extends AbstractBundle {
public class DevKitBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return ourInstance.getMessage(key, params);
@@ -15,14 +15,14 @@
*/
package org.jetbrains.plugins.gradle.util;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author Denis Zhdanov
*/
public class GradleBundle extends AbstractBundle {
public class GradleBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return BUNDLE.getMessage(key, params);
@@ -15,8 +15,8 @@
*/
package org.jetbrains.plugins.gradle.util;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.DynamicBundle;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
@@ -27,7 +27,7 @@ import java.util.ResourceBundle;
/**
* @author Vladislav.Soroka
*/
public class GradleDocumentationBundle extends AbstractBundle {
public class GradleDocumentationBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return BUNDLE.getMessage(key, params);
@@ -1,12 +1,12 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler
import com.intellij.AbstractBundle
import com.intellij.DynamicBundle
import org.jetbrains.annotations.PropertyKey
private const val BUNDLE = "messages.Decompiler"
object IdeaDecompilerBundle : AbstractBundle(BUNDLE) {
object IdeaDecompilerBundle : DynamicBundle(BUNDLE) {
@JvmStatic fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String {
return getMessage(key, *params)
}
@@ -16,10 +16,11 @@
package org.jetbrains.idea.maven.execution;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class RunnerBundle extends AbstractBundle {
public class RunnerBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return ourInstance.getMessage(key, params);
@@ -2,10 +2,11 @@
package org.jetbrains.idea.maven.execution;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class SyncBundle extends AbstractBundle {
public class SyncBundle extends DynamicBundle {
public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return ourInstance.getMessage(key, params);
@@ -2,10 +2,11 @@
package com.intellij.completion;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class StatsCollectorBundle extends AbstractBundle {
public class StatsCollectorBundle extends DynamicBundle {
private static final String STATS_COLLECTOR_BUNDLE = "messages.StatsCollectorBundle";
public static String message(@NotNull @PropertyKey(resourceBundle = STATS_COLLECTOR_BUNDLE) String key, @NotNull Object... params) {
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.PropertyKey;
/**
* @author max
*/
public class XmlErrorMessages extends AbstractBundle {
public class XmlErrorMessages extends DynamicBundle {
private static final XmlErrorMessages ourInstance = new XmlErrorMessages();
@NonNls private static final String BUNDLE = "messages.XmlErrorMessages";