Issue
Is it possible to change the first day of week on JavaFX's DatePicker when applying Arabic locale? I need to change it from Saturday to Sunday.
Solution
I was able to change the first date of the week by injecting the following class within my application:
package sun.util.resources.ar;
import sun.util.resources.LocaleNamesBundle;
public final class CalendarData_ar_SA extends LocaleNamesBundle
{
protected final Object[][] getContents()
{
return new Object[][] { { "firstDayOfWeek", "1" }, { "minimalDaysInFirstWeek", "1" } };
}
}
Do not forget to change the default locale:
public static final Locale SAUDI_AR_LOCALE = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build(); // nu is for numbers
// ....
Locale.setDefault(SAUDI_AR_LOCALE);
EDIT:
The previous solution does not work on latest updates of Java 8 (u152). The proper way to achieve that is to use something called "Locale Sensitive Service Provider".
First, create a custom implementation of CalendarDataProvider:
package io.fouad.utils;
import java.time.DayOfWeek;
import java.util.Locale;
import java.util.spi.CalendarDataProvider;
public class ArabicCalendarDataProvider extends CalendarDataProvider
{
private static final DayOfWeek FIRST_DAY_OF_WEEK = DayOfWeek.SUNDAY;
@Override
public int getFirstDayOfWeek(Locale locale)
{
return (FIRST_DAY_OF_WEEK.getValue() + 1) % 7;
}
@Override
public int getMinimalDaysInFirstWeek(Locale locale)
{
return 1;
}
@Override
public Locale[] getAvailableLocales()
{
return new Locale[]{new Locale("ar", "SA")};
}
@Override
public boolean isSupportedLocale(Locale locale)
{
return locale != null && "ar".equals(locale.getLanguage()) && "SA".equals(locale.getCountry());
}
}
Then create a jar file and package ArabicCalendarDataProvider
as a service provider. i.e. The jar file will have the following files:
META-INF/services/java.util.spi.CalendarDataProvider io/fouad/utils/ArabicCalendarDataProvider.class
The file java.util.spi.CalendarDataProvider
contains the following line:
io.fouad.utils.ArabicCalendarDataProvider
Now, in order to make it working you need to install this jar as an extension either by putting the jar into the default extension directory or by passing the following JVM argument at launch time:
-Djava.ext.dirs=path/to/the/folder/that/contains/the/jar
Note that in Java 9 the locale sensitive services implementations will work directly if the jar is on the application's classpath.
Last, you need to modify the order of locale providers used in your application. i.e. pass the following JVM argument:
-Djava.locale.providers=SPI,CLDR,JRE,HOST
SPI
should be first.
You can test it as follows:
DayOfWeek firstDayOfWeek = WeekFields.of(new Locale("ar", "SA")).getFirstDayOfWeek();
System.out.println("firstDayOfWeek = " + firstDayOfWeek);
In the default behavior the output would be:
firstDayOfWeek = SATURDAY
When applying the custom locale provider and put SPI
as first one the output would be:
firstDayOfWeek = SUNDAY
See:
- LocaleServiceProvider's JavaDoc.
- Lesson: Service Providers for Internationalization.
- Why does the Java Extension Mechanism not check the classpath for an optional package implementing LocaleServiceProvider?
Answered By - Eng.Fouad
Answer Checked By - Robin (JavaFixing Admin)