Set specified locale in wicket where default(for user) are not aviable - wicket

I have properties files oriented for specific language only (page_ru_RU.prop and page_en_GB.prop). Where on this page came user with locale en US - he got exception, because no proper locale found.
Can i in this way make somwhere check to manual set locale if user dont have any aviable locale without make default locale (page.prop)
If I am not clear about, please tell me.

If you create a properties file with just the language only, it will be used for all variants: so instead of page_en_GB.properties, you can have a page_en.properties, which will be used for all en_* sublocales.
You can also have a plain page.peroperties, which will be used for everyone who doesn't fit into a more specific category.
Update: Take two, how to take control of Locale selection completely.
Locale in Wicket is stored in the Session object, it can be manipulated using the getLocale() and setLocale() method. This alone might give you a solution, but you can also intercept calls to these methods to override locale selection automaticlly.
//this is your application class
public class MyApplication extends WebApplication {
#Override
public Session newSession( Request req, Response res ) {
return new MySession( req )
}
}
//this is your session class
public class MySession extends WebSession {
public MySession( Request req ) {
super( req );
}
#Override
public void setLocale( Locale locale ) {
// your locale substitution code goes here, for example:
if( locale.getLanguage().equals( "en" ) ) {
super.setLocale( new Locale( "en", "GB" ) );
}
}
}
Is this the sort of thing you're after?

Related

How can I add language setting entries to existing CDT eclipse projects?

I am following the steps found here to try to add build settings to files in existing Eclipse CDT projects using the LanguageSettingsProvider extension point, but my settings provider doesn't seem to show in the UI, and its methods aren't queried for settings.
I previously succeeded in adding settings to a project using an external settings provider, but I couldn't find a way to add file-specific settings.
I have implemented a subclass of LanguageSettingsSerializableProvider (let's call it MyProvider), and added it to my plugin.xml thus:
<extension
point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider
class="com.example.MyProvider"
id="MyProvider_id"
name="I would like to see this in the UI">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
The class is implemented approximately thus:
public class MyProvider
extends LanguageSettingsSerializableProvider
implements ILanguageSettingsProvider,
IResourceChangeListener,
ILanguageSettingsEditableProvider,
ILanguageSettingsBroadcastingProvider {
/** The ID of this settings provider */
public static final String MY_PROVIDER_ID = "MyProvider_id"; //$NON-NLS-
/**
* Constructor. Initialises super class with appropriate values.
*/
public MyProvider() {
super( MY_PROVIDER_ID , Messages.UiLabel );
}
#Override
public String getId() {
return MY_PROVIDER_ID ;
}
#Override
public String getName() {
return Messages.UiLabel;
}
#Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource resource, String languageId) {
//breakpoint on this line that never gets hit...
return super.getSettingEntries( cfgDescription, resource, languageId );
}
...
}
The real implementation contains some other logic to actually create the settings entries, including registering itself as a resource change listener. The resourceChanged code works fine, calls setSettingsEntries, and then serializeSettings. However, getSettingEntries is never called to obtain these settings.
Is there something I'm missing?
My guess is the plugin.xml is lacking something, but I'm not sure what. There are paragraphs of guidance in the various interfaces that the class implements, but one simple working example would be worth more than a thousand words. I've tried looking at the xml for the built-in settings providers (e.g. GCCBuiltinCompilerSettingsMinGW), but they're defined alongside a lot of other parts of CDT, and it's hard to tell which bits are relevant to my use case.
What I ended up doing was:
someMethod {
final IProject myProject = getProjectFromSomewhere();
final ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription( myProject );
for (ICConfigurationDescription config : projDesc.getConfigurations()) {
try {
ensureMySettingsProvidedFor( (ILanguageSettingsProvidersKeeper) config );
} catch (ClassCastException e) {
logger.log( Level.WARNING, "Unexpected class was not a keeper of language settings:" + config.getClass().getName(), e );
}
}
}
/**
* Will ensure my settings provider is registered as a settings provider for...
* #param settingsKeeper ...the given configuration.
*/
public static void ensureMySettingsProvidedFor(final ILanguageSettingsProvidersKeeper settingsKeeper) {
if (settingsKeeper instanceof CConfigurationDescriptionCache) {
logger.log(Level.SEVERE, "Got non-writable cached settings. We can't update this!! "
+ "How do we get a writeable version?");
return;
}
for ( ILanguageSettingsProvider provider : settingsKeeper.getLanguageSettingProviders() ) {
if (MyProvider.MY_PROVIDER_ID.equals( provider.getId() )) {
return;
}
}
addMyProvider( settingsKeeper );
}
/**
* Adds my language settings provider to the given configuration by means of its ID.
* #param settingsKeeper The existing configuration.
*/
private static void addMyProvider( final ILanguageSettingsProvidersKeeper settingsKeeper ) {
List<String> ids = new ArrayList<String>();
for ( ILanguageSettingsProvider provider : settingsKeeper.getLanguageSettingProviders() ) {
ids.add( provider.getId() );
}
ids.add(MyProvider.MY_PROVIDER_ID);
List<ILanguageSettingsProvider> newProviders = LanguageSettingsManager.createLanguageSettingsProviders( ids.toArray( new String[ids.size()] ) );
settingsKeeper.setLanguageSettingProviders(newProviders);
}
It doesn't feel like the best answer, but it seems to work most of the time.
One problem is knowing when to do this such that it happens for all projects that don't yet have the provider, but doesn't get called repeatedly, or too often.
Another problem is that we sometimes get a CConfigurationDescriptionCache, and then the code can't do anything.
I'm open to better solutions.

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");

Play 2.0 date format

I'm trying to format a date in a Scala template in Play. So far I've written this:
<p>#DateFormat.getInstance().format(deadline)</p>
Where deadline is the date I'm outputting to the web page. However, this uses the JVM's locale and not the one selected by the user.
My app currently supports two locales, Norwegian (no) and English (en). This works well for messages, but not for Dates. So I tried adding a GlobalSettings to intercept each request as shown below, but apparently it's never invoked:
import java.lang.reflect.Method;
import java.util.Locale;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import play.GlobalSettings;
import play.i18n.Lang;
import play.mvc.Action;
import play.mvc.Http.Request;
public class Global extends GlobalSettings {
#SuppressWarnings("rawtypes")
#Override
public Action onRequest(final Request request, final Method actionMethod) {
LocaleContextHolder.setLocaleContext(new LocaleContext() {
public Locale getLocale() {
Lang preferred = Lang.preferred(request.acceptLanguages());
return preferred.toLocale();
}
});
return super.onRequest(request, actionMethod);
}
}
Does someone have a solution to this problem? Is it a known bug in Play? I'm using version 2.0.4.
Thanks!
I tried estmatic's solution, but it didn't discriminate properly between country variants of the same language, for example if my browser's preferred languages were "en_AU" and "en_US" in that order, then it would only use the "en" part, which resulted in a US-style date (with the month first) rather than an Aussie-style one (with the date first, as is right and proper).
My solution was to create a helper class as follows:
public class Formatter extends Controller {
private static final int DATE_STYLE = LONG;
private static final int TIME_STYLE = SHORT;
/**
* Formats the given Date as a date and time, using the locale of the current
* request's first accepted language.
*
* #param date the date to format (required)
* #return the formatted date
* #see play.mvc.Http.Request#acceptLanguages()
*/
public static String formatDateTime(final Date date) {
final Locale locale = getPreferredLocale();
return DateFormat.getDateTimeInstance(
DATE_STYLE, TIME_STYLE, locale).format(date);
}
private static Locale getPreferredLocale() {
final List<Lang> acceptedLanguages = request().acceptLanguages();
final Lang preferredLanguage = acceptedLanguages.isEmpty() ?
Lang.preferred(acceptedLanguages) : acceptedLanguages.get(0);
return new Locale(preferredLanguage.language(), preferredLanguage.country());
}
}
Then in my Scala templates, all I had to do was use (for example):
#import my.package.Formatter
...
Date = #Formatter.formatDateTime(someDate)
This seems cleaner to me than having a lot of Locale construction logic in the templates.
Well you need to provide the locale when you get your DateFormat instance; otherwise it'll just use the system default locale instead of what Play is getting from the browser.
Something like this seems to work:
#DateFormat.getDateInstance(DateFormat.LONG, (implicitly[Lang]).toLocale).format(deadline)
That implicitly[Lang] bit is basically calling Lang.preferred(request.acceptLanguages() just like you were doing in your onRequest() method.

How to handle optional query parameters in Play framework

Lets say I have an already functioning Play 2.0 framework based application in Scala that serves a URL such as:
http://localhost:9000/birthdays
which responds with a listing of all known birthdays
I now want to enhance this by adding the ability to restrict results with optional "from" (date) and "to" request params such as
http://localhost:9000/birthdays?from=20120131&to=20120229
(dates here interpreted as yyyyMMdd)
My question is how to handle the request param binding and interpretation in Play 2.0 with Scala, especially given that both of these params should be optional.
Should these parameters be somehow expressed in the "routes" specification? Alternatively, should the responding Controller method pick apart the params from the request object somehow? Is there another way to do this?
Encode your optional parameters as Option[String] (or Option[java.util.Date], but you’ll have to implement your own QueryStringBindable[Date]):
def birthdays(from: Option[String], to: Option[String]) = Action {
// …
}
And declare the following route:
GET /birthday controllers.Application.birthday(from: Option[String], to: Option[String])
A maybe less clean way of doing this for java users is setting defaults:
GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)
And in the controller
public static Result users(Integer max, Integer page) {...}
One more problem, you'll have to repeat the defaults whenever you link to your page in the template
#routes.Application.users(max = 50, page = 0)
In Addition to Julien's answer. If you don't want to include it in the routes file.
You can get this attribute in the controller method using RequestHeader
String from = request().getQueryString("from");
String to = request().getQueryString("to");
This will give you the desired request parameters, plus keep your routes file clean.
Here's Julien's example rewritten in java, using F.Option: (works as of play 2.1)
import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
// …
}
Route:
GET /birthday controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])
You can also just pick arbitrary query parameters out as strings (you have to do the type conversion yourself):
public static Result birthdays(Option<String> from, Option<String> to) {
String blarg = request().getQueryString("blarg"); // null if not in URL
// …
}
For optional Query parameters, you can do it this way
In routes file, declare API
GET /birthdays controllers.Application.method(from: Long, to: Long)
You can also give some default value, in case API doesn't contain these query params it will automatically assign the default values to these params
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
In method written inside controller Application these params will have value null if no default values assigned else default values.
My way of doing this involves using a custom QueryStringBindable. This way I express parameters in routes as:
GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)
The code for Period looks like this.
public class Period implements QueryStringBindable<Period> {
public static final String PATTERN = "dd.MM.yyyy";
public Date start;
public Date end;
#Override
public F.Option<Period> bind(String key, Map<String, String[]> data) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
try {
start = data.containsKey("startDate")?sdf.parse(data.get("startDate") [0]):null;
end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
} catch (ParseException ignored) {
return F.Option.None();
}
return F.Option.Some(this);
}
#Override
public String unbind(String key) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
return "startDate=" + sdf.format(start) + "&" + "endDate=" + sdf.format(end);
}
#Override
public String javascriptUnbind() {
return null;
}
public void applyDateFilter(ExpressionList el) {
if (this.start != null)
el.ge("eventDate", this.start);
if (this.end != null)
el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
}
}
applyDateFilter is just a convienence method i use in my controllers if I want to apply date filtering to the query. Obviously you could use other date defaults here, or use some other default than null for start and end date in the bind method.

How to implement custom internationalization with gwt?

I want to make custom internationalization for my gwt app. What does this means? Imagine that my app must be internationalized for men and women. (id=men, id=women).
is it possible to make two different .properties files like
MyAppMessages_men_en.properties
MyAppMessages_women_en.properties
MyAppMessages_men_fr.properties
MyAppMessages_men_fr.properties
etc...
and my app host page will be accessed like this for example http://blabla/MyAppHostPage.html?locale=en&id=men
and this must load english version for men.
Thanks.
How about using fictional locale identifiers such as en_US_Men and en_US_Women and so forth for other locales?
(note that you should include a country whenever you include a variant of a locale)
Otherwise, I'd suggest using an abstract factory for your Messages and switch the concrete implementation using deferred binding on a distinct property (men vs. women):
interface MyAppMessagesFactory { MyAppMessages create(); }
class MyAppMessagesFactory_Men implements MyAppMessagesFactory {
#Override
public MyAppMessages create() { return GWT.create(MyAppMessages_Men.class); }
}
class MyAppMessagesFactory_Women implements MyAppMessagesFactory {
#Override
public MyAppMessages create() { return GWT.create(MyAppMessages_Women.class); }
}
You'd then have your MyAppMessages_Men_en.properties and MyAppMessages_Women_en.properties.