 |
Internationalization 101: Setting up a fallback font
Posted by joconner on September 12, 2006 at 11:12 PM | Comments (5)
The Problem
Have you ever seen a desktop application that displays question marks or maybe block symbols instead of the correct characters? You know the characters: ???? or □□□□. Maybe you have localized your app to Japanese or Chinese, and those characters just aren't displayed properly.
The most likely cause of the problem is that you don't have a font capable of displaying the character. The J2SE 5.0 environment has reasonable localized mappings for most host platforms. The mappings allows the JRE to quickly find fonts for the various characters you might want. It maps characters to the fonts that contain the correct glyphs. However, your system may not have a font for every character you want to use. For me, this happens most often on development machines that aren't using a localized operating system for the target locale. However, I've noticed this same problem with some of the new supplementary characters in the Unicode standard, and those characters aren't really common in any locale. For example, Etruscan or Gothic characters just don't show up in common, everyday text...but hey, when you need them, you'll be glad to know you can display them.
The Solution
The solution is to install a capable font. You may have to purchase or create your own font for your particular needs, especially if you need supplementary characters. Regardless how you get the font, you have to install it. You have a choice of course:
- install the font into the host font system and use it by its explicit font name
- tweak the font configuration files to map your installed host font to a logical font...messy and not recommended.
- install the font as a "fallback" font in your JRE.
Installing a Fallback Font
Adding the font to the JRE's fallback directory might be the simplest solution if you just want to display rarely used characters. A fallback font is the last option for the JRE when it tries to find a character glyph. After searching all the typical places for a glyph, the JRE looks in the fallback directory. It will search the fallback directory and use the first font that contains the needed glyph.
Create a fallback font by adding your font to the "fallback" directory:
<JRE_INSTALL_DIR>/jre/lib/fonts/fallback
This directory may not exist on your system. So just create it if it's not already there.
The Results
In the following screenshots, I display some Gothic characters without a fallback and then with a fallback. A font called Code 2001 provides most of the Unicode plane 1 supplementary characters. I've used it for the screen shots here. Fallback fonts aren't always pretty. In fact, they can be downright ugly...but what do you expect from something called a fallback font?

Image 1. No fallback font is available.
|

Image 2. The fallback font displays the Gothic characters.
|
Summary
The JRE uses fallback fonts to display characters when no other appropriate font can be found on your host system. Place your fallback fonts in the jre/lib/fonts/fallback directory. Fallback fonts are your JRE's last resort, so make sure those fonts have the characters you need in a crunch.
More tips?
If you have more tips for getting the most out of your JRE, let me know. I especially like tips that help me internationalize applications. And if I post your tip here, I'll be sure to give you full credit for the idea! You can reach me at john @ joconner dot com.
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
There are a couple of issues with this solution:
- It is barely documented. AFAIK it is mentioned in a single sentence somewhere in the JDK documentation, not even in any JRE documentation.
- It is not deployable via Web Start. So you either have to write an own installer which determines the particular's JRE installation directory, or ask the user to mess with his/her JRE installation. The first item is especially fun if there are multiple JREs installed on the same machine (think Windows..., think platform-specific ways to find more or less all JRE installations). The second means endless opportunities for a user to mess up the installation.
- Normal users might not have write permission to that directory at all. So even if your application would otherwise deploy without elevated rights, this method might require them.
- The change might be global in the sense that if this JRE is shared by several users and applications, they might suddenly all see the change. There is a very slight chance that the change affects other applications and users in some unintentional way.
In fact, your suggestion highlights some long-standing problems with the JRE design. There are multiple places (e.g. the extension mechanism), where the JRE designers use the same mechanism: Throw something in a particular JRE directory, and the JRE will pick it up. And they again and again miss the point. Extensions (fonts, packages or whatever) need to be much finer controllable than just on global JRE level. One needs:
- Per-application extensions
- Per-user, per JRE installation extensions
- Per-local-machine extensions
- Global extensions
The first two need to be installable by a normal user without elevated rights. All installations and the management of extensions should happen via Web Start.
The idea is far from new. I just don't understand why the JRE architects think unmanagable, per JRE extensions will cut it. Yes, the are "cool" from developers perspective. Throw the stuff in and be done with it on the development machine. They are a joke when it come to the deployment of real-world applications.
Posted by: ewin on September 13, 2006 at 08:07 AM
-
Just a couple links for more information:
Posted by: joconner on September 13, 2006 at 02:40 PM
-
ewin, I can understand that you might be frustrated or critical about the JRE extension mechanism. That's fine. However, you have to understand something about what I'm describing in this entry...it is a fallback font mechanism...that's it. It isn't a great solution for providing fonts for an application. It's the fallback solution. This idea is, as you say, far from new. It exists on many platforms.
I think my description of the feature is accurate, and it may be helpful to some people. As you point out, it isn't documented all that well, and it may be difficult to find the documentation anyway. I'm just trying to describe what's there...please don't shoot the messenger...that'd be me!
In a future post, I plan to describe how you can use a font that you want to embed in your app's jar file. That's yet another solution for getting the right font. There's a lot of ways to solve this problem, and the fallback mechanism is just one. Your ideas for future entries are always welcome!
Posted by: joconner on September 13, 2006 at 10:39 PM
-
I have well understood that you are describing a fallback solution. But one which is likely not even deployable at end-user machines and might only be feasable in a development environment.
However, doing something like this in a development environment is outright dangerous. Your JRE then differers from the target environment. A developer who is not or no longer aware of the particular change might assume "if things work here, they also work for the users".
My advice is therefore to never ever use such a fallback solution or any other JRE extension for even the most basic tests in development. Use an original, unaltered, off-the-shelf JRE. If the JRE lacks something, fix it in a way that ensures the fix will be deployed at your user's machines, too.
That is not specific to the JRE or Java. It is not a good idea to do such changes in any kind of development environment.
Regarding the embeding of a font in a jar, are you talking about getResourceAsStream() plus createFont()? Well, yes, that sort of works (since 1.3 or so). Only that you get in trouble with two issues
- You are in trouble if you want system fonts to take precedence over your embeded font if a system font contains the desired glyphs, too. You have to manually code this and you would have to rely on the notoriously unreliable canDisplay...() methods to check if the system fonts can handle a particular character.
- You are in trouble if your embedded font only contains those special glyphs, but you want to display strings which contain a mixture of "normal" and "special" characters. The you have to analyse each string separately, probably convert the data into styled text (another can of worms with a barely documented API) and insert font change attributes where needed.
So you are back to the same problem, the need for a cross-platform, standardised font extension mechanism which is deployable on a per-application level and which does not require to program your own font lookup and string analysis mechanism.
You state there are lots of ways to solve the problem. I claim there are lots of ways to solve 80% of the problem. I want to see one way (a single one, not lots) which fixes 100% of the problem without the need to code my arse off. And here we are back to square one, the sade state of JRE extension mechanisms which don't match real-world requirements.
Posted by: ewin on September 14, 2006 at 07:21 AM
-
It seems like you have an issue with the JRE extension mechanism itself, and I cannot do much about that. However, I can describe what exists today. I can describe the options one has. I cannot create JRE solutions, but I can describe what is available.
You obviously don't like this particular solution, but as you already point out, you don't think there are any good solutions today. I hope you'll agree that I've done a decent job of describing the fallback system even though you may not like that solution. I think we agree that it isn't perfect. It has problems.
You seem to understand the problem better than most people. Do you have a solution? If you have something, I do know people who would be very interested. You might file a bug or a request for enhancement (RFE) that describes what you think should be done to handle the font-character problem.
What is your opinion of JSR 277? It provides some hope that the deployment problem, including fonts, might get better.
Posted by: joconner on September 14, 2006 at 10:17 AM
|