You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Intake should provide some sort of support for localizations. This affects two fields:
Internal localization: All hard-coded strings should be externalized in a Java ResourceBundle and some behaviour might need to be updated in order to work as expected in an localized environment. Some points might need discussion:
Intake has several internal runtime exceptions that the end-user should never see (e.g. ParametricException). These might not need localization.
It might be a good idea to allow users to alter or replace the internal localization logic by providing custom translations. In that case the two entry points are ParametricBuilder and CommandGraph.
External localization: The values in command annotations, specifically description and help, need localization support. The entry point here is the ParametricBuilder.
If localizations use key -> value relationships, as enforced by Java resource bundles, description and help methods would need to return the key. This contradicts the current behaviour where both methods return the actual value, so a support for that old, non localised behaviour is needed.
On both fields, the support should be as flexible as possible and do not enforce any specific way of handling Locales on the user.
Since I need localization support in MyWarp, I have implemented a limited localization support in my own Intake fork (i18n branch). I would be happy to contribute these changes in a PR so there is something to discuss about, if the general direction fits.
One reason why I haven't gotten around to localization is because I was hoping to make localization per-player, especially since the client send its language setting. However, realistically I don't know how many people care about that.
Then the other issue is that there isn't really some localization project I'm aware of that's really suited for it (other than ones in Java web frameworks) so that would mean having some resource loading library specific to Intake, while the rest of your project might use something else. Unless, of course, I make a separate localization lib but I haven't really gotten around to that.
Why not use Java's RessourceBundles? A RessourceBundle implementation can be used without using Java's lookup process (static RessourceBundle.getBundle(String) methods). An even if this lookup process is used, it is completely configurable by using a custom RessourceBundle.Control implementation.
What exactly did you have in mind for per-player localizations? I would have thought that an RessourceProvidersuch as
publicinterfaceResourceProvider {
/** * Gets a ResourceBundle that contains the localised strings applicable in the * context it is called. * * @return the ResourceBundle * @throws java.util.MissingResourceException if such a ResourceBundle does * not exist */ResourceBundlegetBundle();
}
is sufficient as it is left to the user to resolve the currently applicable RessourceBundle (e.g. in MyWarp, I use a ThreadLocal object to keep track of the current user's Locale).
If that is not applicable, the interface could probably get access to the current CommandContext or even a custom context object to wrap other dependencies.
Compared with my previous fork, I changed the approach:
Command annotations can be localize by specifying keys in the annotations that are resolved by a custom resolver the client registered with the ParametricBuilder.
Internal exception messages are not natively localized (as in my fork of version 3). The client is expected to catch all possible exceptions and localize them as desired.However to do so, some internal changes where needed:
Each exception needs to have a single, well defined reason to be thrown (e.g. unqualified usage of InvalidUsageExceptions for missing or wrong sub-commands can no longer be accepted). I added several additional Exceptions for such cases;
Currently the AbstractParametricCallable wraps lots of internal exceptions with InvalidUsageException, the original cause is hidden behind the getCause() method. Since this makes parsing the exceptions a two step-process (catch InvalidUsageException and parse cause) witch is hard to maintain for larger setups, I replaced this wrapping with a DefaultExceptionHandler that can be replaced by clients.
ExceptionHandlers can request an ExceptionContext that contains contextual information that can be used for parsing.
Although unrelated, all public constructors of CommandContext have been deprecated because I suspect the Builder should be used.
There is also a new example for internationalized commands.
@sk89q any chance to get these changes into the master version?
(I suspect that especially (ii.) and (iii.) could be solved differently by requiring callers to use the getCause()method, perhaps sourcing a dedicated ExceptionHandleras I do for parsing ArgumentExceptions in the example. This might be worth to discuss if you are interested in pulling these changes into master.)
Activity
onbjerg commentedon Aug 7, 2015
👍 Your branch seems to be behind the Intake master branch, though.
TheE commentedon Aug 7, 2015
My branch is still on version 3 as I have not (yet) been able to update it and depending projects.
I am still interested in contributing localization support to Intake 4.
sk89q commentedon Aug 14, 2015
One reason why I haven't gotten around to localization is because I was hoping to make localization per-player, especially since the client send its language setting. However, realistically I don't know how many people care about that.
onbjerg commentedon Aug 14, 2015
That sounds like a nice idea.
ewized commentedon Aug 14, 2015
I care about that.
On Fri, Aug 14, 2015 at 12:10 AM マルウェア notifications@github.com wrote:
sk89q commentedon Aug 14, 2015
Then the other issue is that there isn't really some localization project I'm aware of that's really suited for it (other than ones in Java web frameworks) so that would mean having some resource loading library specific to Intake, while the rest of your project might use something else. Unless, of course, I make a separate localization lib but I haven't really gotten around to that.
TheE commentedon Sep 2, 2015
Why not use Java's RessourceBundles? A
RessourceBundleimplementation can be used without using Java's lookup process (staticRessourceBundle.getBundle(String)methods). An even if this lookup process is used, it is completely configurable by using a customRessourceBundle.Controlimplementation.What exactly did you have in mind for per-player localizations? I would have thought that an
RessourceProvidersuch asis sufficient as it is left to the user to resolve the currently applicable
RessourceBundle(e.g. in MyWarp, I use a ThreadLocal object to keep track of the current user's Locale).If that is not applicable, the interface could probably get access to the current
CommandContextor even a custom context object to wrap other dependencies.sk89q commentedon Sep 2, 2015
It forces a ThreadLocal upon the user, although I suppose it's not a big issue.
I suppose the other reason why i haven't gotten around to it is because I haven't added localization to WE yet.
TheE commentedon Feb 15, 2016
I just updated my fork for version 4 of Intake.
Compared with my previous fork, I changed the approach:
ParametricBuilder.InvalidUsageExceptions for missing or wrong sub-commands can no longer be accepted). I added several additional Exceptions for such cases;AbstractParametricCallablewraps lots of internal exceptions withInvalidUsageException, the original cause is hidden behind thegetCause()method. Since this makes parsing the exceptions a two step-process (catchInvalidUsageExceptionand parse cause) witch is hard to maintain for larger setups, I replaced this wrapping with aDefaultExceptionHandlerthat can be replaced by clients.ExceptionContextthat contains contextual information that can be used for parsing.CommandContexthave been deprecated because I suspect the Builder should be used.There is also a new example for internationalized commands.
@sk89q any chance to get these changes into the master version?
(I suspect that especially (ii.) and (iii.) could be solved differently by requiring callers to use the
getCause()method, perhaps sourcing a dedicatedExceptionHandleras I do for parsingArgumentExceptions in the example. This might be worth to discuss if you are interested in pulling these changes into master.)