removing obsolete keys from messages.properties generated by string externalizing - eclipse

I am using "Externalize Strings" widget of Eclipse. On externalizing strings, a messages.properties file is generated with key value pairs.
Say the messages.properties looks like this:
Test_msg1=Add
Test_msg2=Remove
Test_msg3=Include
Say I have a file Test.java with code:
String add = Messages.getString("Test_msg1");
String remove = Messages.getString("Test_msg2");
String include = Messages.getString("Test_msg3");
Next, if I edit Test.java file and remove the two strings "remove" and "include" then I would want the messages.properties file to be updated such that Test_msg2 and Test_msg3 are removed. Is there a way to do this ? Or do I have to edit messages.properties file manually everytime I delete a string from a huge java file?
Thanks,
Sony

When you externalize strings from java file via 'Externalize dialog', you should get a Message.java and message.properties like below,
public class Message extends NLS {
private static final String BUNDLE_NAME = "com.xxx.ui.internal.Message"; //$NON-NLS-1$
//Generic Strings:
public static String Str1;
public static String Str2;
static {
loadMessages();
}
public static void loadMessages() {
NLS.initializeMessages(BUNDLE_NAME, Message.class);
}
}
Str1=Add
Str2=Remove
If no java code uses the string "Str1", you would find them and remove them via right clicking the Message.java or message.properties, then clicking the context menu item 'source' - 'find broken externalized strings'.

Related

How to read a specific language.properties file?

Here's my problem. I need to generate PDF in particular language chosen by user. Some informations are in language.properties files and I cannot manage to read other files than the current site language.
For example current language is Spanish and User select German. I'd like to read language_de.properties.
I've tried to use:
String Lang=LanguageUtil.get(LanguageUtil.getLocale('de'), "Mykey");
but without sucess, it always returns "Mykey"
If I use :
String Lang=LanguageUtil.get(HttpServletRequest, "Mykey");
It works, but It's the site language and not the one I want.
Any Ideas?
One option is that you have forgotten to define de_DE in your portal-ext.properties for locales.enabled:
#
# Specify the locales that are enabled by default.
#
locales.enabled=en_US,de_DE,es_ES
Another possibility is that the locale is not enabled for your portal instance. You should check that in the admin UI of your instance.
In both cases LanguageUtil.getLocale('de') will return null - and this will return the given key from LanguageUtil.get. You can verify that by printing the result of LanguageUtil.getLocale('de') and LanguageUtil.getLocale('de_DE') (should both be null). Just add the locale to the enabled ones and you are good.
A third option applies, if you have defined the messages in the resource bundle of your portlet (usually you define the messages in a hook or OSGI bundle to use them in more than one portlet). In that case LanguageUtil.get(Locale, String) doesn't know which portlet you are in and can't access the resource bundle of that portlet. That's the difference to LanguageUtil.get(HttpServletRequest, String), which retrieves the portlet from the request.
In that case you have to retrieve the resource bundle from the config given to your Portlet.init(PortletConfig) method. Or you mimic the implementation of LanguageUtil.get(HttpServletRequest, String) with a locale specific parameter:
public class MyLanguageUtil {
public static String get(HttpServletRequest request, Locale locale, String key) {
if (request == null) {
return key;
}
PortletConfig portletConfig = (PortletConfig) request.getAttribute("javax.portlet.config");
if (portletConfig != null) {
ResourceBundle resourceBundle = portletConfig.getResourceBundle(locale);
if (resourceBundle.containsKey(key)) {
return LanguageUtil.get(resourceBundle, key, key);
}
}
return LanguageUtil.get(locale, key);
}
}
ok got it to work.
I added a class for each language in my module language
import java.util.Enumeration;
import java.util.ResourceBundle;
import org.osgi.service.component.annotations.Component;
import com.liferay.portal.kernel.language.UTF8Control;
#Component(
property = { "language.id=es_ES" },
service = ResourceBundle.class
)
public class EsResourceBundle extends ResourceBundle {
#Override
protected Object handleGetObject(String key) {
return _resourceBundle.getObject(key);
}
#Override
public Enumeration<String> getKeys() {
return _resourceBundle.getKeys();
}
private final ResourceBundle _resourceBundle = ResourceBundle.getBundle(
"content.Language_es_ES", UTF8Control.INSTANCE);}
thanks for help
For those who need this to be a little more generic.
Add a small class to your portlet that accesses the portlets ResourceBundle:
public class [MyPortlet]LanguageUtil {
public static String get (Locale locale, String key) {
ResourceBundle resourceBundle = ResourceBundle.getBundle("content.Language", locale, UTF8Control.INSTANCE);
return LanguageUtil.get(resourceBundle, key);
}
public static String format (Locale locale, String pattern, Object[] arguments) {
ResourceBundle resourceBundle = ResourceBundle.getBundle("content.Language", locale, UTF8Control.INSTANCE);
return LanguageUtil.format(resourceBundle, pattern, arguments);
}
}
and export it with the help of the bnd.bnd file of the portlet like:
Export-Package: [path.to.my.util]
This way it can be used in OSGI modules and regular JAVA classes for example like this:
[MyPortlet]LanguageUtil.get(serviceContext.getLocale(), "my-language-string");

RepositoryItem from List&Label .lst file

Currently we are using a WPF application for creation/editing of List&Label Templates, but we are considering to move to the WebDesigner. Because we use project includes we need to use the repository mode.
I've been trying to import our existing templates, but I run into some issues regarding the RepositoryItemDescriptor. To create a RepositoryItem object you have to give a Descriptor in the constructor, but I cannot find any info regarding how you get it from the generated .lst file.
The data that we have at our disposal are:
TemplateType: List or Form
TemplateData: content of the .lst file (byte[])
IsMainTemplate: bool, is a "project include" or not
File name: name of the .lst file
The RepositoryItem constructor requires: string internalID, string descriptor, string type, DateTime lastModificationUTC.
What I have now is:
public class TemplateBaseModel : RepositoryItem
{
// Properties
// we have our own Ids and modification date, override RepositoryItem properties
public new InternalID => $"repository://{{{Id}}}";
public DateTime LastModificationUTC => ModifiedOn;
public TemplateBaseModel() : base($"repository://{{{Guid.NewGuid()}}}", /* ?? */, RepositoryItemType.ProjectList.Value, DateTime.Now) { }
public TemplateBaseModel(string internalID, string descriptor, string type, DateTime lastModificationUTC) : base(internalID, descriptor, type, lastModificationUTC) { }
}
In the documentation I can only find what it is (internal metadata that is serialized into a string, and can be edited with the class RepositoryItemDescriptor), but not how it's created or how you can get it, and if I try to debug the example I get (in the CreateOrUpdate() method)#2#PgUAAENoS19QYWNrZWQAeNqd1E1PE1EYxfHfmsTvMAyJEeLY8iKCtpChU5MmvAiOC2NcjDCYmqFtZkaEqF9dXThgsTVGt/fm+Z9zz3lyv3/r2HXlQiFwKVeqDI2NdIVWPdIWCuRGTo2dGRp5ryv0Suq5yKpNoUCllhk5kymMjeS6QtdyldCuHfcs6FgUiQQSqUQgEk3dJY70pF57oS8wURo7N1TIBd64Z0GgY1HfodRA6rXAqVIgdN+SK21tbZlnt4o9J41W2OjNo9Qy72Y421OcVGzvD6R9fQcNcdb7A4WhSm3FQ4GhWu7CimUrt6T5rJvJacruHcruHEosldo38PI3ykjmQi7Qk4ilYoElJ/qOvTJwoi+Z4s33daMeeGDJiyna8szs725+zf6vmz8Tf+71U5WJzGmT/5ncucxHhdoXE6VcJVe6lFsWCGdOQzsCb+ds8I3T6R2+2/qv/ZjNvit0IjcxVhmqjZWuDZpXhHfanE2rKzSQCO0o53Ceamn5rGdTrC3Ws6YtkuiJbYts2LJlXWRbbNWayIbEE7E9sZ4Na9Y91vdVR+vWx9+9pa5NmvwKhVaTzQe5U7WWQqX+R+q+TKV20PxI54ZyZ0I7LmXK5t17PkkcOnSkdKxtT6pwLNbVnava0brt6abP1txGfwD+q8AH, which doesn't help either.
Any idea how to properly create a RepositoryItem from a .lst file? or how to create/get the descriptor?
You should try and use the class RepositoryImportUtil from the combit.ListLabel23.Repository namespace. This helper class does all the hard work for you. Given an IRepositoryinterface and the lst file in place, the required code would be something like
IRepository listLabelRepository = <yourRepository>;
using (ListLabel LL = new ListLabel())
{
LL.FileRepository = listLabelRepository;
using (RepositoryImportUtil importUtil = new RepositoryImportUtil(listLabelRepository))
{
importUtil.ImportProjectFileWithDependencies(LL,
#"<PathToRootProject>");
}
}
If this method is not what your require, the helper class has a couple of other methods as well to help you importing existing projects.

How can I use values from Eclipse Preference Pages to initialize external tool parameters?

I've created Eclipse Plugin from default template with Preference Pages. There are some preference parameters, two of them are String. I also created custom External Tool launch configuration in this Plugin and I use one of String parameters (let it be P_PATH) mentioned before to initialize one of tool's fields by default (using SetDefaults method). The problem is that it doesn't work as I suggested. When I launch this plugin (in another Eclipse instance) I go to Window->Preferences->Sample Preferences where I can edit and save field values. But after I'm done (when i enter something to field connected with P_PATH value there) I create new external tool of selected type and String parameter of selected field (the one tied to P_PATH, let it be "File Path") is inialized by the value that was specified in Plugin, not the one I entered into Preference Pages form. So, I want String value I enter in Preference Pages to be passed to External Tool as one of its parameters and when I create new External Tool of selected type it should be there (as default). How can I do that? I tied one External Tool field and one Preference Pages field to the same string parameter but looks like it's not properly passed to External Tool after all.
Added some code, there are three classes for Preference Pages and the forth one is for Launch Configuration Tabs. Here is only relevant code:
public class PreferenceConstants {
public static final String P_PATH = "pathPreference";
}
public class PreferenceInitializer extends AbstractPreferenceInitializer {org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
public void initializeDefaultPreferences() {
store.setDefault(PreferenceConstants.P_PATH,"Default value");
}
}
public class PreferencePage
extends FieldEditorPreferencePage
implements IWorkbenchPreferencePage {
public PreferencePage() {
super(GRID);
setPreferenceStore(Activator.getDefault().getPreferenceStore());
setDescription("A demonstration of a preference page implementation");
}
public void createFieldEditors() {
addField(new FileFieldEditor(PreferenceConstants.P_PATH,
"&Console compiler path:", getFieldEditorParent()));
}
public void init(IWorkbench workbench) {
}
}
public class LaunchConfigurationTabs extends AbstractLaunchConfigurationTabGroup {
#Override
public void setDefaults(ILaunchConfigurationWorkingCopy configuration){
configuration.setAttribute("org.eclipse.ui.externaltools.ATTR_LOCATION", PreferenceConstants.P_PATH);
}
}
The line:
configuration.setAttribute("org.eclipse.ui.externaltools.ATTR_LOCATION", PreferenceConstants.P_PATH);
Just sets the attribute value to 'pathPreference' - this does not do anything to look up the value in the preferences.
You can look up the preference value at that point:
IPreferenceStore prefStore = Activator.getDefault().getPreferenceStore();
String value = prefStore.getString(PreferenceConstants.P_PATH);
configuration.setAttribute("org.eclipse.ui.externaltools.ATTR_LOCATION", value);
I don't think you can do anything that will make the attribute value automatically update if the preference changes.

Attach a CSV in Mail

I want to attach a csv file in mail(grails)
The file in the path is already present. I am using the following code
sendMail {
multipart true
from "$senderName <$fromAddress>"
to toAddress
cc message.cc
subject message.subject
body content.plaintext
html content.html
attachBytes './web-app/ReadyOrdersFor-${vendor.name}','text/csv', new File('./web-app/ReadyOrdersFor-${vendor.name}').readBytes()
}
Error prompted is.
java.io.FileNotFoundException: ./web-app/ReadyOrdersFor-${vendor.name}.csv (No such file or directory)
neither this works prompting the same error
attachBytes './web-app/ReadyOrdersFor-${vendor.name}.csv','text/csv', new File('./web-app/ReadyOrdersFor-${vendor.name}.csv').readBytes()
The issue is that you trying you use the file path string as a GStringImpl, but the string is enclosed in single quotes. GStringImpl is natively supported in groovy in double quotes.
You code should be
attachBytes "./web-app/ReadyOrdersFor-${vendor.name}",'text/csv', new File("./web-app/ReadyOrdersFor-${vendor.name}").readBytes()
This link should help you understand the difference between using single and double quotes in groovy.
Instead of trying to get a File reference using new File(path), use the Spring ResourceLoader interface. The ApplicationContext implements this interface, so you can get a reference to it from a controller (for example) like this:
class MyController implements ApplicationContextAware {
private ResourceLoader resourceLoader
void setApplicationContext(ApplicationContext applicationContext) {
resourceLoader = applicationContext
}
def someAction() {
String path = "classpath:/ReadyOrdersFor-${vendor.name}"
File csvFile = resourceLoader.getResource(path).file
}
}
I'm not 100% sure the path value above is correct, you may need to remove the '/'

Is there a way to capitalize the first letter of a value of a variable in Eclipse (Helios) code templates

I have a code template with a variable and I would like to capitalize(just the first letter) the value of this variable only in some occurrences. Is there a way to do this?
The template code is as follows - I would like to capitalize Property Name in my function names...
private $$${PropertyName};
${cursor}
public function get${PropertyName}()
{
return $$this->${PropertyName};
}
public function set${PropertyName}($$value)
{
$$this->${PropertyName} = $$value;
}
Please Note: This is a template for use with code templates in the IDE (not in PHP). For details see: http://www.ibm.com/developerworks/opensource/tutorials/os-eclipse-code-templates/index.html
I also want this and tried to build a custom TemplateVariableResolver to do it. (I already have one custom resolver in place that generates new UUIDs a la http://dev.eclipse.org/blogs/jdtui/2007/12/04/text-templates-2/.)
I made a custom resolver bound to capitalize:
public class CapitalizingVariableResolver extends TemplateVariableResolver {
#Override
public void resolve(TemplateVariable variable, TemplateContext context) {
#SuppressWarnings("unchecked")
final List<String> params = variable.getVariableType().getParams();
if (params.isEmpty())
return;
final String currentValue = context.getVariable(params.get(0));
if (currentValue == null || currentValue.length() == 0)
return;
variable.setValue(currentValue.substring(0, 1).toUpperCase() + currentValue.substring(1));
}
}
(plugin.xml:)
<extension point="org.eclipse.ui.editors.templates">
<resolver
class="com.foo.CapitalizingVariableResolver"
contextTypeId="java"
description="Resolves to the value of the variable named by the first argument, but with its first letter capitalized."
name="capitalized"
type="capitalize">
</resolver>
</extension>
that I would use like this: (I am working in Java; I see that you do not appear to be)
public PropertyAccessor<${propertyType}> ${property:field}() {
return ${property};
}
public ${propertyType} get${capitalizedProperty:capitalize(property)}() {
return ${property}.get();
}
public void set${capitalizedProperty}(${propertyType} ${property}) {
this.${property}.set(${property});
}
As of Eclipse 3.5, the problem I am having is that my custom resolver does not get a chance to re-resolve once I've specified a value for the property variable. It appears that the Java Development Tools (Eclipse JDT) do this dependent template variable re-resolution via a mechanism called MultiVariableGuess within the JavaContext (see addDependency()). Unfortunately for us, that mechanism does not seem to be exposed, so I/we can't use it to do the same (without lots of copy-and-paste or other redundant work).
At this point, I am giving up again for a while and will keep typing the leading-lowercase and leading-uppercase names separately into two independent template variables.