Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 316386 - Avoid hardcoding resource bundle names
Summary: Avoid hardcoding resource bundle names
Status: CLOSED INVALID
Alias: None
Product: CDT
Classification: Tools
Component: cdt-core (show other bugs)
Version: 7.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact: Doug Schaefer CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-06-09 17:22 EDT by John Cortell CLA
Modified: 2010-06-14 08:13 EDT (History)
1 user (show)

See Also:
john.cortell: review? (cdtdoug)


Attachments
Solution (13.31 KB, patch)
2010-06-09 17:23 EDT, John Cortell CLA
john.cortell: iplog-
Details | Diff
Updated solution; supports both common practices (13.91 KB, patch)
2010-06-09 19:52 EDT, John Cortell CLA
john.cortell: iplog-
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John Cortell CLA 2010-06-09 17:22:17 EDT
It's always irked me that NLS class derivatives have a hardcoded reference to their package name, thus making them fragile in the case of package refactoring.

This adds a utility method that lets CDT and CDT clients avoid that. It also updates instances in the core plugin for reference.

Will commit post-Helios unless someone objects.
Comment 1 John Cortell CLA 2010-06-09 17:23:16 EDT
Created attachment 171580 [details]
Solution
Comment 2 John Cortell CLA 2010-06-09 17:23:49 EDT
Doug,  please review.
Comment 3 Doug Schaefer CLA 2010-06-09 17:31:11 EDT
Looks OK to me, but then I'm not an i18n expert. Is Vivian watching this bug?
Comment 4 Sergey Prigogin CLA 2010-06-09 17:34:43 EDT
NLS.initializeMessages(clazz.getPackage().getName() + ".messages", clazz); //$NON-NLS-1$

violates the prevailing convention that the properties file has the same name as the corresponding NLS file. It should be changed to: NLS.initializeMessages(clazz.getName(), clazz);
Comment 5 John Cortell CLA 2010-06-09 17:39:02 EDT
(In reply to comment #4)
> NLS.initializeMessages(clazz.getPackage().getName() + ".messages", clazz);
> //$NON-NLS-1$
> 
> violates the prevailing convention that the properties file has the same name
> as the corresponding NLS file. It should be changed to:
> NLS.initializeMessages(clazz.getName(), clazz);

I don't believe that will work. In 100% of the cases I've seen, the properties file starts with a lowercase 'm', while the class name is uppercase. I'm pretty sure the resource bundle name is case sensitive.

The utility method also specifically states in the javadoc that it is not completely general purpose but it caters to the very common scenario of having a "messages.properties" where the NLS derivative is.
Comment 6 Andrew Gvozdev CLA 2010-06-09 17:43:07 EDT
Is CDT appropriate place for this solution? Shouldn't you ask the platform for setting standardized solution in NLS class?
Comment 7 Sergey Prigogin CLA 2010-06-09 17:54:38 EDT
(In reply to comment #5)
In cdt.core + cdt.ui there are 36 messages.properties files and 36 SomeClassMessages.properties files. I prefer the latter naming convention that is cleaner in my opinion.
Comment 8 John Cortell CLA 2010-06-09 17:59:42 EDT
(In reply to comment #7)
> (In reply to comment #5)
> In cdt.core + cdt.ui there are 36 messages.properties files and 36
> SomeClassMessages.properties files. I prefer the latter naming convention that
> is cleaner in my opinion.

And you are certainly entitled to that opinion. But the fact is that there are many others who think differently (like me), and who will continue using the former regardless of your opinion. We can require them to hardcode the package name or we can help them out with a utility method. In fact, why not add a varant utility method to cater to your preference? I have no problem with that.
Comment 9 John Cortell CLA 2010-06-09 18:01:52 EDT
(In reply to comment #6)
> Is CDT appropriate place for this solution? Shouldn't you ask the platform for
> setting standardized solution in NLS class?

It is an *adequate* place for it, IMO. I'm not going to ask the platform to
standardize something when they've obviously designed it to be flexible, and
it's unlikely they're going to add a utility to handle a scenario that has
become common in practice. I don't think it's inappropriate to house something
like this in CDT. I don't see why we can't make things a little easier for
ourselves...and if we know CDT clients can benefit, too, expose it to them as
well. I was initially going to add this to an internal package, but thought CDT
clients would appreciate it if we expose it to them.

My position is that CDT need not restrict its usefulness to CDT-isms, as long
as we're not encouraging a violation of platform guidelines, or leading clients
down some arbitrary path. The convention of having a Messages.class co-located
with a messages.properties is extremely pervasive.
Comment 10 Doug Schaefer CLA 2010-06-09 18:08:53 EDT
BTW, how does ICU4J fit into this. This has been an Eclipse requirement forever and I can't tell whether we satisfy it or not. Does that force us into a solution for message bundles?
Comment 11 John Cortell CLA 2010-06-09 18:12:54 EDT
(In reply to comment #10)
> BTW, how does ICU4J fit into this. This has been an Eclipse requirement forever
> and I can't tell whether we satisfy it or not. Does that force us into a
> solution for message bundles?

I don't see any overlap between ICU4J and this bugzilla.
Comment 12 Doug Schaefer CLA 2010-06-09 18:17:49 EDT
(In reply to comment #11)
> (In reply to comment #10)
> > BTW, how does ICU4J fit into this. This has been an Eclipse requirement forever
> > and I can't tell whether we satisfy it or not. Does that force us into a
> > solution for message bundles?
> 
> I don't see any overlap between ICU4J and this bugzilla.

OK. Some day I'll try to figure out what ICU4J is. But I enjoy the entertainment of not meeting artificially created requirements from non-contributors :).

BTW, whatever you do, don't break open declaration from the String to the value in the properties file. Without that message bundles are brutal to understand.
Comment 13 Sergey Prigogin CLA 2010-06-09 18:22:02 EDT
(In reply to comment #8)
I think we should follow
http://www.eclipse.org/articles/Article-Internationalization/how2I18n.html.

Platform plugins are in agreement with it, org.eclipse.ui and
org.eclipse.jdt.ui don't contain any messages.properties files.
Comment 14 Andrew Gvozdev CLA 2010-06-09 18:33:03 EDT
(In reply to comment #13)
> (In reply to comment #8)
> I think we should follow
> http://www.eclipse.org/articles/Article-Internationalization/how2I18n.html.
> Platform plugins are in agreement with it, org.eclipse.ui and
> org.eclipse.jdt.ui don't contain any messages.properties files.

Externalize strings wizard suggests messages.properties by default, that's where they are coming from.
Comment 15 John Cortell CLA 2010-06-09 18:36:26 EDT
(In reply to comment #13)
> (In reply to comment #8)
> I think we should follow
> http://www.eclipse.org/articles/Article-Internationalization/how2I18n.html.
> 
> Platform plugins are in agreement with it, org.eclipse.ui and
> org.eclipse.jdt.ui don't contain any messages.properties files.

Am I overlooking something? I don't see where this document explicitly states a preference for using a common base filename for the NLS class and the properties file. That may be the case in the examples provided, but it is not stated as a guideline. That some plugins in the platform prefer that approach is fine. If they thought it an important-enough guideline to follow, they should have added it to their document.
Comment 16 John Cortell CLA 2010-06-09 18:40:37 EDT
(In reply to comment #12)
> BTW, whatever you do, don't break open declaration from the String to the value
> in the properties file. Without that message bundles are brutal to understand.

Huh? You've lost me here.
Comment 17 Sergey Prigogin CLA 2010-06-09 18:46:51 EDT
(In reply to comment #15)
The article, in general, is not written as a rigid set of rules. It starts with:
Summary 
This article is a roadmap for writing Eclipse plug-ins destined for the international market. We'll begin with a brief review of the motivations and technical challenges of internationalization, followed by step-by-step instructions of how to internationalize your Eclipse plug-in.

The example is part of the step-by-step instructions, isn't it?
Comment 18 John Cortell CLA 2010-06-09 19:09:46 EDT
(In reply to comment #17)
> (In reply to comment #15)
> The article, in general, is not written as a rigid set of rules. It starts
> with:
> Summary 
> This article is a roadmap for writing Eclipse plug-ins destined for the
> international market. We'll begin with a brief review of the motivations and
> technical challenges of internationalization, followed by step-by-step
> instructions of how to internationalize your Eclipse plug-in.
> 
> The example is part of the step-by-step instructions, isn't it?

That's a stretch. Sorry, Sergey. You're not going to convince me. (a) Andrew pointed out the externalization wizard follows the 'messages.properties" convention. (b) There is no explicit guideline and you're trying to dissect and spin an introductory paragraph to support your position that it is a guideline. (c) I like the consistency of having a same-named file house the string properties in a package, just as I like to use "Activator.java" for a plugin's activator. Other developers apparently do, too. (d) I've found 146 instances of "messages.properties" in the platform plugins.

Again, I'm not trying to sell you on my preference; I see no further point in having you sell me on yours. I've added a utility to cater to a pervasive, long-standing practice--one not only in CDT but in the platform. I don't see a problem.
Comment 19 Sergey Prigogin CLA 2010-06-09 19:16:16 EDT
(In reply to comment #18)
> I've added a utility to cater to a pervasive,
> long-standing practice--one not only in CDT but in the platform. I don't see a
> problem.

If we say that both naming conventions are legitimate, them NLSUtil should not give preference to one over another.
Comment 20 John Cortell CLA 2010-06-09 19:17:33 EDT
(In reply to comment #19)
> (In reply to comment #18)
> > I've added a utility to cater to a pervasive,
> > long-standing practice--one not only in CDT but in the platform. I don't see a
> > problem.
> 
> If we say that both naming conventions are legitimate, them NLSUtil should not
> give preference to one over another.

Which is why I offered to add a variant for the other convention. Both benefit from not having to hardcode the package name.
Comment 21 Sergey Prigogin CLA 2010-06-09 19:21:31 EDT
(In reply to comment #20)
> Which is why I offered to add a variant for the other convention. Both benefit
> from not having to hardcode the package name.

I'm ok with that.
Comment 22 Doug Schaefer CLA 2010-06-09 19:29:45 EDT
Another thing to throw into the mix, how are we doing with Babel? It's an opportunity to get contributions to translations.
Comment 23 John Cortell CLA 2010-06-09 19:52:16 EDT
Created attachment 171592 [details]
Updated solution; supports both common practices

The utility method now takes a parameter to support both common use cases (see discussion above). I couldn't think of decent names for individual methods so I added a parameter and kept it to a single method.
Comment 24 Sergey Prigogin CLA 2010-06-09 20:00:49 EDT
(In reply to comment #23)

How about initializeClassMessages and initializePackageMessages?
Comment 25 John Cortell CLA 2010-06-09 20:18:57 EDT
(In reply to comment #24)
> (In reply to comment #23)
> 
> How about initializeClassMessages and initializePackageMessages?

I find that confusing, as it implies two distinct types of message sets: a set for a class, and a set for a package. According to the guidelines, there should be a single properties file per package, and the class scope is burned into the string property name, e.g:

   MyClass_hello_world
   AnotherClass_good_night
Comment 26 Andrew Gvozdev CLA 2010-06-09 22:56:09 EDT
(In reply to comment #16)
> (In reply to comment #12)
> > BTW, whatever you do, don't break open declaration from the String to the value
> > in the properties file. Without that message bundles are brutal to understand.
> Huh? You've lost me here.
Yeah, that's a real problem. Check this out:
0. Find a reference to one of the variables in one of Message class, for example Messages.EclipseVariablesVariableSupplier_illegal_variable (EclipseVariablesVariableSupplier.java:86).
1. Hover the mouse pointer over it. Before the patch I see "message.properties" and "Illegal usage of Eclipse variable: {0}". After the patch it just shows that the type is "String".
2. Hold Ctrl and then hover mouse pointer. Before patch you get suggestion "Open in 'message.properties'". If you click on it - it navigates right to the definition in 'message.properties'. After the patch it does not.
3. In 'message.properties', position the cursor on EclipseVariablesVariableSupplier_illegal_variable. Press F3. OK, this one still works. So does Ctrl-[mouse click].

Non-working cases 1) and 2) are no-go. I strongly suggest to submit a patch to platform so we are guaranteed to keep the tooling support. You don't know if it is going to be rejected or accepted.
Comment 27 Doug Schaefer CLA 2010-06-09 22:59:42 EDT
(In reply to comment #26)
> (In reply to comment #16)
> > (In reply to comment #12)
> > > BTW, whatever you do, don't break open declaration from the String to the value
> > > in the properties file. Without that message bundles are brutal to understand.
> > Huh? You've lost me here.
> Yeah, that's a real problem. Check this out:
> 0. Find a reference to one of the variables in one of Message class, for
> example Messages.EclipseVariablesVariableSupplier_illegal_variable
> (EclipseVariablesVariableSupplier.java:86).
> 1. Hover the mouse pointer over it. Before the patch I see "message.properties"
> and "Illegal usage of Eclipse variable: {0}". After the patch it just shows
> that the type is "String".
> 2. Hold Ctrl and then hover mouse pointer. Before patch you get suggestion
> "Open in 'message.properties'". If you click on it - it navigates right to the
> definition in 'message.properties'. After the patch it does not.
> 3. In 'message.properties', position the cursor on
> EclipseVariablesVariableSupplier_illegal_variable. Press F3. OK, this one still
> works. So does Ctrl-[mouse click].
> 
> Non-working cases 1) and 2) are no-go. I strongly suggest to submit a patch to
> platform so we are guaranteed to keep the tooling support. You don't know if it
> is going to be rejected or accepted.

That's not good. I'd vote -1 if this is the case.
Comment 28 John Cortell CLA 2010-06-09 23:32:50 EDT
(In reply to comment #27)
> > Yeah, that's a real problem. Check this out:
> > [snip]

Crap. There's some real voodoo magic going on there. Simply add

private static final String BUNDLE_NAME= "org.eclipse.cdt.internal.core.cdtvariables.messages"; //$NON-NLS-1$

to the Messages.java file and the feature is restored...even though 'BUNDLE_NAME' is not used anywhere. This tells me the feature is relying on some pretty fragile, heuristic methods for getting to the literals in the properties file. I guess I shouldn't be surprised by that, but it sucks to see a tooling feature get in the way of a code improvement. In other words, the JDT guys have pretty much forced us to hardcode the package name in the java file (or lose these powerful capabilities). Just doesn't seem right, but I understand the difficulties of trying to determine something at build-time (edit, really) that can only truly be established at run-time.

At this point, I'm just going to chuck this down the shoot. I've already wasted too much time (mine and Sergey's) on this.
Comment 29 Sergey Prigogin CLA 2010-06-12 20:02:02 EDT
(In reply to comment #28)
The things are actually not that bad. To see for yourself open TraceControlView.java and select TraceControlView_action_Refresh_label. Notice that both 1) and 2) work. Navigate to TracepointsMessages.java and notice that the initialization code is pretty decent: NLS.initializeMessages(TracepointsMessages.class.getName(), TracepointsMessages.class);
Comment 30 Doug Schaefer CLA 2010-06-12 20:12:53 EDT
(In reply to comment #29)
> (In reply to comment #28)
> The things are actually not that bad. To see for yourself open
> TraceControlView.java and select TraceControlView_action_Refresh_label. Notice
> that both 1) and 2) work. Navigate to TracepointsMessages.java and notice that
> the initialization code is pretty decent:
> NLS.initializeMessages(TracepointsMessages.class.getName(),
> TracepointsMessages.class);

Of course my vote was conditional and not an outright veto :).
Comment 31 John Cortell CLA 2010-06-13 15:57:46 EDT
(In reply to comment #29)
> (In reply to comment #28)
> The things are actually not that bad. To see for yourself open
> TraceControlView.java and select TraceControlView_action_Refresh_label. Notice
> that both 1) and 2) work. Navigate to TracepointsMessages.java and notice that
> the initialization code is pretty decent:
> NLS.initializeMessages(TracepointsMessages.class.getName(),
> TracepointsMessages.class);

You are focusing on your particular preference of naming the .properties file after the NLS class. In that case, yes, it looks like the JDT features (1) and (2) work because it is able to predict what WhateverClass.class.getName() will return (not too difficult).

I opened this bug primarily to address the other scenario--where there's a messages.properties file. Again there are MANY such cases. In that case, I see no way around having to hardcode the resource bundle name. Thus, my patch is still unusable.
Comment 32 Sergey Prigogin CLA 2010-06-14 01:04:42 EDT
(In reply to comment #31)

I thought the primary concern was a hardcoded package name. This problem does have a solution, at least for property files named after classes. If you don't like this solution, you can close the bug.
Comment 33 John Cortell CLA 2010-06-14 08:13:34 EDT
(In reply to comment #32)
> (In reply to comment #31)
> 
> I thought the primary concern was a hardcoded package name. This problem does
> have a solution, at least for property files named after classes. If you don't
> like this solution, you can close the bug.

I think it's a great technique. I'm saying it only addresses one approach. I took a survey and that approach is by far less common than the specific one I was trying to address. The instances of using "messages.properties" vs using the NLS class name differ by about a factor of 2X. 

Plus, you've somehow managed to change the purpose of the bug report (formally by changing the abstract line). I initially created the bug report in order to introduce a utility class to let us avoid hardcoding the package name in *new code*. I never intended to go through and change existing classes to use the utility, except that I did so for one plugin in order to provide some reference usage. 

What you've done is come up with a *technique* to avoid harcoding the package in the less common cases. It doesn't involve a new utility class, so there is no patch to contribute, and thus there really is no need for a bug. If you want to go through and convert all the existing classes to use your technique, I guess you could do that with a bug. I'm not going to do that. Are you? If not, then again, I don't see a case for an open bugzilla. What would be better is if you email the cdt-dev list and say, hey, in the future, you can use this technique to avoid hardcoding the package name.

I've closed the bug. If you are going to sign up to update all existing usages that can be resolved with your technique, feel free to reopen it.