Requirements     

               
Prerequisite knowledge
This article covers beginning concepts in working with text in SWF content. General knowledge of the Flash Professional authoring interface and ActionScript 3 fundamentals is advised.
Required products
Flex Builder 3 (Download trial)
 
 
   
User level
Intermediate
   
Great applications are able to reach users around the world. However, developing truly global applications requires presenting information in the way that your users around the globe expect to see it: not only in their own language but according to their own cultural conventions. This article shows you how the newly available flash.globalization package in the Flash Player 10.1 public prerelease makes it easy to display numbers, dates, and times; sort words or sentences; and even capitalize letters in a manner consistent with the expectations of every user.
 
Localization and internationalization is challenging on two levels. Beyond language barrier issues, cultural conventions present a special challenge because they must be followed dynamically: rather than a translator adapting text once and for all, your application must generate basic data such as ordered lists, dates, and numeric values and present them in a manner familiar to each user. Myriad existing cultural conventions do not make this an easy task.
 
For example, an ordered list (of product manufacturers, book or friend names, etc.) will help a user quickly get to the desired entry—but only if your application follows the ordering rules that he or she uses every day. Misunderstanding prices or dates is certainly not found anywhere in your application's specifications; yet, cross a national border and you will find that people read and interpret the same written value in completely different ways. Even users who speak your language are likely to have different requirements: one need only compare, for example, how dates are written in London and New York to get an idea of the problem. In short, complying with the cultural conventions of each user is not just a matter of increasing user comfort and productivity (both important, of course) but also of preventing critical misunderstandings.
 
Until now, developers of SWF applications for Flash were left on their own to handle this problem, but that is about to change. The flash.globalization package enables you to enable your SWF application to account for all these cultural differences with a minimum of ActionScript code.
 
Using the classes of the flash.globalization package is generally simple, but you may first want to go through a quick refresher about globalization: its major aspects (support for multilingual text, cultural conventions, and localizability) and how it differs from (and is a prerequisite for) localization.
 
Before you start using the data formatters and collators, be sure to understand how the whole package works (what it can and cannot do, how it reports errors, and so on) and to develop a firm grasp on locales whose identifiers are key to choosing the right cultural convention (several locales may be needed for different purposes). This article aims to clarify those concepts along the way.
 

 
Globalization nano-primer

Even if you do not plan to translate your application (taking the localization step), you will often find customers hailing from unexpected locations, people who can read (if not speak) your language well enough to use your product and would love to do so. Of course, you still need to meet them halfway by allowing them to write text in their own language and showing them information tailored to their cultural conventions. That first step is globalization, and it should also address localizability (the separation and management of localizable assets, to ensure that localization can easily be done).
 
 
Multilingual text
Supporting multiple writing systems is the first critical step. Based either on an alphabet or a set of ideograms, a writing system is a collection of graphical shapes (sometimes called script) and the rules used to assemble them into words and sentences. In practice, users often need to use more than one script in the same document. For example, a Japanese user will probably want to write the name and address of a German customer in its original form, using Latin characters. To make this possible, an application typically uses a multilingual character set to represent text. Unicode is the gold standard adopted by all major platforms and, because Flash Player uses it too, so do your ActionScript applications.
 
While the use of Unicode guarantees that users will be able to input and store any kind of text, displaying it properly is another matter. Fortunately, Flash Player now provides advanced typesetting capabilities, supporting the major writing systems and accessible through the Text Layout Framework. Be careful when embedding fonts, however: each font provides a limited repertoire of symbols, and hard-coding the use of one font for all users is likely to result in display errors with many languages.
 
 
Diversity of cultural conventions
We all know that applications must be easy to use—but it's not just a matter of intuitive controls and visuals. Textual information that you display must be easy to find and understand. Even if all members of your audience speak the same basic language, if they live in different regions of the world, they are likely to sort words and write dates or even numbers in slightly different ways.
 
For example, imagine searching for a colleague's telephone number in a company directory application. Often, the first step that you will take is simply typing your colleague's name in a search box, expecting the results to contain names written in an equivalent form. You will most likely find capitalization irrelevant and are hoping that searching for "Leblanc" will also find "LeBlanc." You may be unsure about diacritical marks (or how to type them) and would probably like to find "Öhlund" even if you searched for "Ohlund." These and many other types of equivalences are commonly used and expected, sometimes with subtle differences between cultures.
 
Now you're browsing the results of your search and you'd probably like to see them sorted in a way that lets you quickly scan and find the item you need. For example, if you had searched for "Peter" and found 30 people, a list sorted by family names would certainly be easier to use. The order that you have learned to expect, however, is conditioned by your native language.
 
If you were Italian, you would probably look for "Peter Öhlund" after "Peter Ohlin" but before "Peter Olsdal" (see Table 1). If you were German and accustomed to the order of classic telephone directories, you would look for it before "Peter Ohlin" (and soon after "Peter Oehler"). Yet if you were Swedish, you would look for it not only after "Peter Olsdal" but, in fact, even after "Peter Zorn"! Ordering the list according to each user's expectations enables them to use the application effectively.
 
Ordering varies with the reader's language
Table 1. Ordering varies with the reader's language
Like text ordering, numeric and date formats are highly variable across cultures (see Table 2). The fractional part of a number may start with a period in one region, with a comma in another; negative values may be identified by a minus sign placed before or after the value. In either case, a currency symbol may precede or follow the sign. Using a convention familiar to each user (rather than the developer) will help avoid misreading and confusion.
 
Examples of number formats
Table 2. Varying conventions for numbers and dates
Obviously, this requires those culturally sensitive operations to be performed at runtime, after identifying the user and his or her cultural preferences—perhaps by obtaining user preferences from the operating system or by letting the user indicate them within the application. After that, let the flash.globalization classes do the hard work for you.
 

 
The flash.globalization package

Introduced with Flash Player 10.1, the flash.globalization package is a collection of classes that harness the cultural support capabilities of the underlying operating system and make it easy for your application to follow the cultural conventions of individual users. Before you dig deeper into how to use each class, there are a few things about the package that you should know.
 
 
Package at a glance
The package contains the following main classes:
 
  • NumberFormatter: represents generic numeric values
  • CurrencyFormatter: represents monetary values
  • DateTimeFormatter: represents calendar values
  • Collator: compares words or sentences (typically to sort them)
  • StringTools: provides text transformation services such as capitalization
  • LocaleID: provides utility methods for parsing and processing strings containing a locale identifier
The package provides other supporting classes, a few of which define constants. For example, NationalDigitsType defines constants that specify the type of numerals (also called digits) that will be used by the number and currency formatters. This enables your application to use European numerals (0, 1, 2, 3, etc.), Arabic-Indic numerals (٣, ٢, ١, ٠, etc.), or numerals from other languages, for example.
 
To use a service, the general procedure is very simple:
 
  1. Determine the locale to use. Keep in mind that the user may often prefer a locale different from that of the application's user interface, and might even choose slightly different locales for different services (for example, collation versus number formatting).
    For Adobe AIR applications, constant LocaleID.DEFAULT will generally bring the right choice (the user preference stored by the operating system for the requested service).
     
    For online applications, it could be preferable to comply with preferences obtained from the enclosing website.
     
    Finally, in special cases, you might prefer using the locale of the document or paragraph (if your application supports that concept). We will talk about this in more detail in section, "Selecting a locale."
     
  2. Instantiate a service object, using the identifier of the desired locale. For example:
var numFormatter:NumberFormatter = new NumberFormatter(LocaleID.DEFAULT);
  1. Configure the service as desired by setting its properties. For example:
numFormatter.fractionalDigits = 5;
  1. Use the service as many times as desired. For example:
var valueOfPiAsText:String = numFormatter.formatNumber(Math.PI);
 
Error checking
To check for errors, read property lastOperationStatus of the service object. It always contains one of the constants defined by class LastOperationStatus, including NO_ERROR:
 
var numberFormatter:NumberFormatter = new NumberFormatter(LocaleID.DEFAULT); if(numberFormatter.lastOperationStatus != LastOperationStatus.NO_ERROR) { // The number formatter could not be created exactly as requested. }
There are three main categories of warnings or errors that can occur while using the flash.globalization package:
 
  • When instantiating a service (for example, a number formatter), the locale that you requested may not be available. In that case, a fallback locale is found and substituted. A service object, configured for the fallback locale, is returned. In many cases, you can ignore the warning and go on using the service. I will explain this in more detail in the section, "Selecting a locale."
  • A service property that you tried to set is not supported by the user's operating system. The request is ignored and the configuration of the service remains unchanged.
    When customizing a service by setting its properties (for example, to make the date and time formatter use a custom pattern), you are facing two risks: you might be inadvertently passing a bad value (for example, an invalid pattern), especially if that value comes from the user; and the operating system might simply not support the requested feature. By checking the lastOperationStatus immediately after such operations, you can fall back on supported settings and let the user know what is happening.
  • A production operation (formatting, parsing, transforming text) failed, either because of invalid input values or because it is not supported by the user's operating system. Depending on the type of value that it returns, the failing method will generally produce a blank text string or the special value NaN (not a number). You might want to create wrapper functions to handle such problem in the way most appropriate for your application.
Functions from the flash.globalization package do not throw exceptions unless you pass an invalid argument such as a null reference (in which case an instance of class Error is likely to be thrown). As long as you take care of calling functions properly, you do not need to worry about exceptions.
 
 
Flash or Flex?
If you are familiar with the Flex framework, you have probably seen its NumberFormatter and DateFormatter classes. The classes presented here serve similar purposes, but are substantially different.
 
The flash.globalization package is built into Flash Player, so your application can use it even if it is not built on top of Flex. Obviously, you can also use it in your applications built with Flex; however, since flash.globalization classes are not associated to any MXML tags, you must write ActionScript code to use them.
 
Unlike the formatters in Flex 3, the flash.globalization package relies on the operating system to perform most operations, so your application has the same cultural capabilities as other applications running on the user's computer. It can comply with the cultural preferences set by each user; it can even use custom locales if the operating system allows creating them. Compared to those of Flex 3, the formatters of the flash.globalization package provide additional features, such as support for various types of numerals, placements of the negative sign, grouping styles, and more. In the future, Flex will most likely take advantage of the flash.globalization package.
 
 
Capabilities may (and do) vary
Keep in mind that Flash Player generally depends on the underlying operating system to perform culturally sensitive operations. This means that you may get slightly different results across platforms.
 
Operating systems vary in the number or choice of cultural conventions that they support. Even for a given community (for example, speakers of Italian), different operating systems may produce slightly different results (date formats could be slightly different). Those differences may be caused by the evolving nature of cultural conventions or they may be the result of a design choice. Generally, those differences do not diminish usability: users know what to expect from their computer and will be at ease seeing the same results in your SWF application.
 
Be careful to avoid tying data integrity to a particular implementation of cultural support. For example, if a critical algorithm relies on a sorted data collection, any change in the sort order would likely break the application. If a culturally specific collation order is used, there are no guarantees that it will remain unchanged (or even available) in the long run or that it will be consistent across operating systems. Generally, culturally sensitive processing should only be performed just in time to present information to the user, not to process or store internal data.
 
One final word of caution: While most classes in the flash.globalization package let you set properties intended to control behavior, that does not give your SWF application the ability to create custom locales. Setting a property will work only insofar as the operating system on the user's computer fully supports it. After setting each one, remember to check the lastOperationStatus property. A wise approach is to change only the few properties that control fundamental output variations, such as the length of the fractional part with the number and currency formatters.
 

 
Selecting a locale

Before using a service from the flash.globalization package, you must select the user's culture. Think of a locale as a collection of cultural conventions specific to a community (for example, English speakers in Australia).
 
 
Locale identifiers
Each locale is uniquely identified through a conventional code stored in a String and compliant with Unicode Technical Standard #35. In a nutshell, a locale identifier looks like this: en-Latn-CA. The first part is a two- or three-letter language code (in this example, en stands for English). It is optionally followed with a four-letter code that identifies the script (Latn stands for the Latin alphabet). Finally, an optional two- or three-capital-letter code (or, in special cases, a three-digit code) indicates the region (CA stands for Canada). More rarely, a fourth element may specify a variant.
 
The only required element in a locale identifier is the language code. However, sharing a language does not guarantee that cultural conventions are equally shared. For example, speakers of English in the United States write dates differently than people in the United Kingdom. Indicating the region is therefore common.
 
Many languages are written with only one script. For example, German is written only with the Latin alphabet. In those cases, the script is normally omitted from the locale identifier and therefore implied (as in de-AT, for speakers of German in Austria). By contrast, Serbian may be written with either the Cyrillic or Latin alphabet. If you do not specify the script, Flash Player will automatically select the prevalent choice. Avoid ambiguity by using sr-Cyrl-RS or sr-Latn-RS.
 
 
The LocaleID class
Generally, you can simply use a String object to store a locale identifier; but if you want to obtain information related to a locale, the class LocaleID provides the means to do so.
 
Creating a LocaleID object is simple:
 
import flash.globalization; var localeId:LocaleID = new LocaleID("de");
After constructing the LocaleID object with the identifier de, method getScript() will return Latn, indicating that Latin is the preeminent writing system used to write German; and method getRegion() will return DE to signify Germany as the default choice.
 
One particularly useful method of class LocaleID, namely isRightToLeft(), allows you to know the direction in which a language is normally written. That information is generally necessary to typeset the text properly. For example, a date formatter created for locale ar-SA (Arabic, Saudi Arabia) will produce text written in Arabic (month and weekday names) that must be laid out from right to left. Knowing the direction of the text produced by the formatter allows you to display it properly with the Text Layout Framework component of Flash Player.
 
 
Locale fallback
Whenever you request a culturally aware service (for example, a number formatter), you must specify the locale that it should use. Because the list of supported locales varies from one operating system to another, the locale that you requested (on the user's behalf) may be unavailable. In that case, Flash Player will attempt to select the most suitable locale from those available. This is done by first trying to match the language of the locale that you requested and then refining the choice by trying to match the writing system and the region. For example, if you request de-CH but only de-DE is available, the latter is selected. If you do not specify a field (for example, the writing system or the region), a default value (based on preeminence) will be automatically assumed. For example, if you specify de, Flash Player will try to match de-Latn-DE.
 
Because locale fallback will generally give you the best available choice, you can simply go on using the service that you just instantiated. If you want more control, check the service's lastOperationStatus property immediately after construction: LastOperationStatus.USING_FALLBACK_WARNING indicates that a fallback locale was selected (it will still match the language that you requested but other fields, like the region, may be different); LastOperationStatus.USING_DEFAULT_WARNING indicates that the fallback is the user preference obtained from the operating system (LocaleID.DEFAULT), selected as a last resort; in that case, even the language may be different from what you had requested.
 
In addition, you can always inspect the identifier of the requested locale as well as the identifier of the locale effectively obtained by using properties requestedLocaleIDName and actualLocaleIDName of the service object:
 
var numberFormatter:NumberFormatter = new NumberFormatter("de-DE"); if(numberFormatter.lastOperationStatus != LastOperationStatus.NO_ERROR) { // Custom function warnUserOfFallbackLocale() is implemented by the // application. It could display an alert to warn the user that // numeric values will be displayed using an unexpected convention. warnUserOfFallbackLocale(numberFormatter.requestedLocaleIDName, numberFormatter.actualLocaleIDName); }
Beware that merely comparing the requested and actual locale identifiers for equality (requestedLocaleIDName == actualLocaleIDName) would likely produce misleading results. For example, requesting fr-Latn-FR will probably return fr-FR; though the identifiers are not an exact match, they both point to the same effective locale.
 
 
One locale does not rule them all
Ideally, a single locale per user could be used for all functionalities, but reality may be different. Because translation is expensive, the user interface of the application is likely to be available in a limited number of localized versions. By contrast, culturally aware services like those from the flash.globalization package support much greater diversity at no extra cost to you, the application developer. For example, if you only provide an American English, French, and Japanese version of the user interface, a user in London may choose en-US (English, United States) for the user interface but en-GB (English, United Kingdom) for number and date formats. For collation rules (used for searching and ordering), the same user might choose yet another locale. Major operating systems (like Mac OS X) support such freedom of choice, but taking advantage of it requires the use of several locale identifiers, one for each functionality.
 
The constant LocaleID.DEFAULT represents for each service the locale preferred by the user, as indicated by the operating system. For example, if the user has configured the system to use locale en-GB (English, United Kingdom) for number formats, instantiating a NumberFormatter with LocaleID.DEFAULT will produce a formatter configured according to locale en-GB. And if the same user has configured the system to use locale en-IN (English, India) for date formats, instantiating a DateTimeFormatter with LocaleID.DEFAULT will produce a formatter configured for locale en-IN. In other words, depending on the user's choice, LocaleID.DEFAULT may very well represent different locales for different services.
 
 
Deciding which locale to use
Early after your application starts, you may want to determine the locales most suitable for the user. Several strategies are possible, and choosing the right one requires looking at the nature of your application.
 
An AIR application should typically behave just like any other desktop application installed on the system and therefore adopt the choice of locale made by the user in the operating system's settings. For services provided by the flash.globalization package, you only need to use the special value LocaleID.DEFAULT: it will be automatically matched to the user's choice for the service being requested. By contrast, for the language of their user interface, AIR applications should use property flash.system.Capabilities.languages to retrieve the user's preference from the operating system. Notice that this is languages, not language—which also exists but is substantially different:
 
  • The property language returns the language of the operating system's user interface, rather than the user's preferred locale, and supports fewer locales than languages.
  • The property languages returns an array of locale identifiers. If, like Mac OS X, the operating system allows the user to specify a list of preferred locales, the array contains that list, in order of decreasing user preference (in other words, the locale preferred by the user is the first in the array); locales to use as preferred fallback follow. Otherwise (for example, on Windows), the array contains a single entry (the user locale). Even in that case, it is more dependable than property language. Note that property languages is only available to AIR applications.
If you are instead developing an online SWF application that needs to be well-integrated into a larger website, you probably want both to use the same locale. While navigating to the site, the user may have selected a locale, either implicitly, through the browser's language settings, or explicitly through a user interface implemented by some other code on the site. Use the FlashVars property of Flash Player (or a URL query string) to let the HTML page pass the locale identifiers to the SWF file. You can retrieve the values through this.root.loaderInfo.parameters or, in Flex, through Application.application.parameters.
 
Finally, if you are creating a large client-server application, you may want to let the user choose locales through a preferences panel in your application. Store those settings locally in a flash.net.SharedObject or, if your application requires users to sign in, on your server along with the user's account information. Choosing the default locale for the sign-in page can be done either by retrieving the value locally stored in a shared object or by receiving the browser's language settings from an HTML page, as explained earlier.
 
 
Using a locale chain
As I explained earlier, using the choices made by the user within the operating system for culturally aware services is easy: simply use LocaleID.DEFAULT whenever you instantiate a service. An ancillary benefit is that the locales selected by the user within the operating system are essentially guaranteed to be available, since they were picked from a list supplied by the system itself.
 
There are other cases, however, where the locale preferred by the user is not guaranteed to be available:
 
  • The locale preferred for the user interface of applications: the user may have expressed a preference for Dutch, but there is no guarantee that a given application will be available with its user interface localized in that language.
  • Locales picked and stored within the application itself (for example, stored with user account information on a server, for a client-server application): the user may access the same application, using the same user account, from different machines running different operating systems and supporting different arrays of locales.
In those cases, there is no guarantee that the user's preferred locale is actually available, and locale fallback becomes much more likely. It then becomes attractive to let the user control the fallback to some degree by specifying, rather than a single choice of locale (for a given service), a list of locales (sometimes called a locale chain) ordered by decreasing preference. The first locale in the list will be used if available; otherwise, the next in the list will be tried, and so on. For example, if the user requests ro-RO, fr-FR, it, en-GB, the application should first try to obtain the service for locale ro-RO (or, by default, another Romanian-language locale); if the system does not support that locale, the application should then try locale fr-FR, and so on. Ultimately, if none of the user's choices are available, the application should fallback on LocaleID.DEFAULT, since it is guaranteed to be installed and obviously understood by the user.
 
Instead of iterating through this chain of preferred locales every time the application needs a globalization service, you can decide, at startup, which locale to use by intersecting the list of available locales for a given service with the list of preferred locales specified by the user for that service. Class LocaleID has a method just for that purpose: determinePreferredLocales(). Using it is simple: you supply a vector of strings (a vector is a typed array) containing the list of preferred locales and another containing the list of available locales. It returns the list of available locales that are on the preferred list, in the preferred order. You can then safely pick the first locale in the list that was returned.
 
Rather than providing a strict intersection of both lists, the determinePreferredLocales() method will perform some amount of fallback to select the most suitable locale, giving more weight to the language than to the writing system and region. For example, if the user requested de-AT, fr-FR but only de-DE, en-US, fr-FR were available (and not de-AT), then de-DE, fr-FR would be returned. Though it does not appear in the list of preferred locales, de-DE leads the resulting list because it provides a favorable match for de-AT.
 
How can you find out which locales are available for a given service? Each service class in the flash.globalization package has a static method named getAvailableLocaleIDNames() that precisely returns such a list. If you are instead trying to determine the best choice of language for the application's user interface, provide a function that returns such a list. For an online application, the list should preferably be initialized from a data file retrieved from the server, allowing for new language packs to be added later and then automatically found by users asking for them.
 
In the following example, we will assume that your application supplies a function named getUserPreferredLocaleIDsForNumberFormatting() returning, in the form of a vector of strings, the locale chain specified by the user for number formatting:
 
import flash.globalization; var availableLocales:Vector.<String>; var preferredLocales:Vector.<String> = getUserPreferredLocaleIDsForNumberFormatting(); var localeForNumberFormatting:String; // Check the ordinary number formatters. availableLocales = NumberFormatter.getAvailableLocaleIDNames(); preferredLocales = LocaleID.determinePreferredLocales(preferredLocales, availableLocales, ""); // Fallback on the default locale if necessary. localeForNumberFormatting = (preferredLocales.length > 0 ? preferredLocales[0] : LocaleID.DEFAULT);
 
Build once, reuse often
Once you have obtained the identifier of the most suitable locale, you may want to instantiate the service objects that you will commonly need throughout the application. This will avoid creating a multitude of service objects, saving memory and execution time:
 
// Ordinary number formatter. var defaultNumberFormatter:NumberFormatter = new NumberFormatter(localeForNumberFormatting); Currency formatter used with Euro currency. var defaultEURMoneyFormatter:CurrencyFormatter = new CurrencyFormatter(localeForCurrencyFormatting); defaultEURMoneyFormatter.setCurrency("EUR","€"); // Date and time formatters, used for short dates and short times. var defaultShortDateFormatter:DateTimeFormatter = new DateTimeFormatter(localeForDateTimeFormatting DateTimeStyle.SHORT, DateTimeStyle.NONE); var defaultShortTimeFormatter:DateTimeFormatter = new DateTimeFormatter(localeForDateTimeFormatting DateTimeStyle.NONE, DateTimeStyle.SHORT); // Collators used for sorting and for matching. var defaultSortingCollator:Collator = new Collator(localeForCollation, CollatorMode.SORTING); var defaultMatchingCollator:Collator = new Collator(localeForCollation, CollatorMode.MATCHING); // Text transformations. var defaultTextUtilities = new StringTools(localeForTextTransformations);

 
Formatting ordinary numbers

The need to track quantities may begin at the origin of writing itself, and there are many ways to represent numeric values. Showing a representation familiar to each user increases comfort and avoids costly misunderstandings.
 
 
Culturally sensitive number formats
Most people around the world now use a variant of the positional decimal system: each number is represented with a series of digits whose position indicates their magnitude. A fractional separator is placed between the integral and fractional parts of the number. In very large numbers, additional separators may be used to group digits and improve legibility. A special symbol or convention indicates whether the number is positive or negative. All of those elements are conventional and vary by culture.
 
For example, consider the value 123456 and one quarter. Figure 1 shows how it should appear to different users. Notice how the fractional separator and the grouping separator can vary. In India the position of the grouping separator itself is not only different but also variable: every two digits, but starting at the third lower digit. Finally, observe the use of Devanagari numerals in Hindi.
 
Examples of number formats
Figure 1. Examples of number formats
From the examples above, you can see how the text 1.125 would be understood as one and one eighth by an American reader but as a value one thousand times larger by a German reader. Being cultural aware may help you avoid costly mistakes!
 
 
Neutrality can also be a good thing
When storing persistent data (for example, in a database or a file) or exchanging data with some other process, interoperability and reliability are paramount. At those times, you should either store numbers in binary form (as int, uint, or Number) or in a plain (culturally independent) text format, such as what is produced by the method toString(). This ensures that any application, running on any platform, will be able to read the data without errors. When you need to display a numeric value to the user, on the other hand, use the NumberFormatter class from the flash.globalization package to ensure that your user will correctly read and understand the value.
 
 
Using the NumberFormatter class
At this point, you should have already identified your user's preferred locale and stored it in a String. Now, you can simply create a NumberFormatter instance and use one of its format methods; for example, use formatNumber() to format a floating-point value stored in an object of type Number:
 
var numberFormatter:NumberFormatter = new NumberFormatter(selectedLocale); var value1Text:String = numberFormatter.formatNumber(123456.125); var value2Text:String = numberFormatter.formatInt(123456);
Remember that if the platform does not fully support the locale that you specified, Flash Player may not be able to create the exact formatter that you requested. In that case, it will substitute a fallback. You can find out whether this happened by testing the lastOperationStatus property of the class NumberFormatter immediately after creating the object. If it indicates anything other than LastOperationStatus.NO_ERROR, check the value of the actualLocaleIDName property to find out which locale was used as fallback. Fallback is described in more detail in the section, "Selecting a locale."
 
 
Customizing the number formatter
The NumberFormatter class provides properties that let you check what conventions are used by a given formatter. For example, use the decimalSeparator property to see the symbol placed before the fractional part. You can also change the values of those properties, thus affecting the behavior of the formatter.
 
For example, in special cases, you might wish to display numbers without the use of grouping separators. The useGrouping property lets you control this:
 
var numberFormatter:NumberFormatter = new NumberFormatter("ru‑RU"); var withGrouping:String = numberFormatter.formatNumber(123456.25); numberFormatter.useGrouping = false; var withoutGrouping:String = numberFormatter.formatNumber(123456.25)
The variable withGrouping now contains 123 456,25 (a non-breaking space is used as grouping separator) while variable withoutGrouping now contains 123456,25.
 
Other properties let you control the output more finely. The fractionalDigits property specifies the maximal length of the fractional part. However, be aware that the type of rounding performed depends on the operating system.
 
Set the digitsType property if you prefer using a different set of numerals (such as the Indian numerals, specified with constant NationalDigitsType.DEVANAGARI). Yet again, be aware that alternate numerals are not uniformly supported across operating systems (check the lastOperationStatus property).
 
Moreover, keep in mind that one principal benefit of the NumberFormatter class is to select the correct format automatically for the locale that you specified; tampering with the format may produce results that puzzle your users.
 
 
Decoding numeric values typed by the user
If the user types a numeric value, you will probably need to turn it into a real Number so that you can perform additional calculations with it. The parse() and parseNumber() methods of NumberFormatter will let you do so safely, recognizing users' conventions according to their locale:
 
import flash.globalization; var numberFormatter:NumberFormatter = new NumberFormatter("ar-SA"); if(numberFormatter.lastOperationStatus != LastOperationStatus.NO_ERROR) { // Need some error handling here... trace("Could not use the requested locale!"); } var value:Number = numberFormatter.parseNumber("١٢٣٤٥٦٫٢٥-"); if(numberFormatter.lastOperationStatus != LastOperationStatus.NO_ERROR) { // Need some error handling here... trace("Could not parse the numeric value!"); }
If the operating system supports the locale ar-SA (speakers of Arabic in Saudi Arabia), the example above should store the negative value –123456.25 (minus one hundred twenty-three thousand, four hundred fifty-six and one quarter). Notice that, in Saudi Arabia, the negative sign is postfixed.
 
The parser can recognize any of the supported numerals, so you do not need to worry about setting the digitsType property to match the user's input.
 
When using the parseNumber() method, you need to be careful: leading and trailing white space will be ignored but if the input text contains anything other than the numerals and separators expected by the formatter, the special value NaN (not a number) will be returned. For example, a leading plus sign (+) would trigger such an error.
 
If your input text contains more than just a number, you can use the parse() method instead. This method will stop at the first unexpected character and, rather than a Number, return an instance of class NumberParseResult containing the value so far decoded (rather than NaN), the index of the number's first character and the index at which parsing stopped. This enables your application, for example, to iterate through text to decode several numbers.
 

 
Formatting monetary amounts

Monetary amounts are characterized by the inclusion of a currency code or symbol. The class CurrencyFormatter is similar to NumberFormatter, but provides additional methods and properties to handle currency.
 
 
Culturally sensitive currency formats
As for ordinary numeric values, the written representation of monetary values varies greatly across cultures, particularly in the placement of the currency symbol.
 
For example, consider the value 123456 and one quarter, expressing an amount in dollars. In Figure 2, observe how the currency symbol can be placed before or after the rest of the number, and may or may not be separated from it with a space.
 
Examples of monetary amounts
Figure 2. Examples of monetary amounts
Even within a community, monetary formats may differ from ordinary numeric formats. For example, in the United States, the negative value of 123456 and one quarter will be shown as –123,456.25 if it is an ordinary numeric value (and therefore formatted with class NumberFormatter) but its monetary equivalent will be rendered as ($123,456.25) by class CurrencyFormatter, using parentheses rather than a negative sign.
 
 
Neutrality still good
Just as for ordinary numeric values, reserve the use of the culturally sensitive currency formatter for direct interaction with the user. If you need to persistently store a monetary amount (in a database or a file), use the value's binary form or a culturally neutral text representation (like the one produced by method toString() of class Number) to ensure that it can be decoded reliably by any application on any platform. Store the currency's identification in the form of an unambiguous and universally recognized ISO 4217 code (for example, "USD"), not as a symbol such as "$".
 
 
Using the CurrencyFormatter class
Create an instance of class CurrencyFormatter using a locale identifier, just as you did with NumberFormatter.
 
var moneyFormatter:CurrencyFormatter = new CurrencyFormatter(selectedLocale);
As with NumberFormatter, a fallback locale may have been selected. See the discussion about NumberFormatter or the section "Selecting a locale" for more about this.
 
Equipped with your currency formatter, you are probably eager to format your first values. But something is missing: Which currency are you using?
 
 
Choosing the currency
A default currency is associated to each locale. In practice, that is irrelevant. A grouping or fractional separator may be a cosmetic convention, but the currency symbol represents a tangible unit that cannot be changed at will. If you are based in Sidney, you might require all customers to pay you in Australian dollars. Even if you decide to accommodate European customers by allowing payments in euros, you will first need to convert all amounts using the exchange rate in effect at the time of the transaction; only then can you display the resulting amounts.
 
Even if you feel confident that the default currency associated to the requested locale is the one desired, do not rely on that assumption! First, the default currency may vary by operating system. It may also change over time (for example, a country might join the Eurozone). A few countries commonly use more than one currency. Finally, if the locale which you requested is not found at runtime, a fallback locale will be used—and it is likely to have a different default currency. Your accountant may not be pleased with the results.
 
It just makes sense to keep a firm grip on the currency symbol (or code) displayed by the currency formatter. Fortunately, there is a simple method to do so: immediately after instantiating the formatter, set the currency as desired using the method setCurrency(), passing two arguments: an ISO 4217 currency code (for example, USD for United States dollars) and a symbolic representation (for example, $).
 
Now you can use the formatter safely:
 
var moneyFormatter:CurrencyFormatter = new CurrencyFormatter(selectedLocale); moneyFormatter.setCurrency("USD", "$"); var valueText:String = moneyFormatter.format(123456.25);
By default, the currency formatter will use the ISO 4217 code for the currency. This provides two benefits: first, ISO 4217 codes are internationally recognized and do not need to be localized; second, unlike currency symbols (which can represent more than one currency), ISO codes are unambiguous. Consider, for example, the dollar sign. Several sovereign countries use the same symbol $ for their currency (whether they call it "dollar" or not). In the United States, it represents the United States dollar; in Australia, it represents the Australian dollar. To avoid ambiguity, the symbol must effectively be localized: the US dollar being shown as US$ to an Australian user but as just $ to an American user; and the Australian dollar being shown as just $ to an Australian user but as A$ or AU$ to an American user.
 
Once you are confident that you obtained the correct symbol (adequately localized for the current user) for the desired currency, simply pass the value true as the second parameter to the format() method and the currency symbol will be used instead of the ISO code:
 
var valueWithSymbol:String = moneyFormatter.format(123456.25, true);
 
Customizing the currency formatter
Like the ordinary NumberFormatter, the class CurrencyFormatter lets you read key settings and change them if desired. The observations and caveats discussed with NumberFormatter also apply here.
 
 
Decoding monetary values typed by the user
If the user types a monetary value, you will probably need to turn it into a real Number, so that you can perform calculations with it (for example, to compare the amount of a proposed payment with the balance of an account). Using the parse() method of the CurrencyFormatter class will let you do so safely:
 
import flash.globalization; var moneyFormatter:CurrencyFormatter = new CurrencyFormatter("hi-IN"); if(moneyFormatter.lastOperationStatus != LastOperationStatus.NO_ERROR) { // Need some error handling here... trace("Could not use the requested locale!"); } var parseResult:CurrencyParseResult = moneyFormatter.parse("-रु. १,२३,४५६.२५"); if(moneyFormatter.lastOperationStatus != LastOperationStatus.NO_ERROR) { // Need some error handling here... trace("Could not parse the monetary value!"); }
If the operating system supports the locale hi-IN (speakers of Hindi in India), the example above should store the negative value –123456.25 (minus one hundred twenty-three thousand, four hundred fifty-six and one quarter) in parseResult.value, while parseResult.currencyString will receive the currency symbol "रु." (the Indian rupee).
 
When using the currency parser, you need to be careful: leading and trailing white space will be trimmed; text containing anything other than the numerals and separators expected by the formatter will be interpreted as the currency symbol if its position matches the currency pattern, and will cause the special value NaN (not a number) to be stored otherwise. For example, a leading plus sign (+) would cause the parse() method to produce NaN.
 
Interpreting the currency symbol may be difficult because, even within a single community of users, more than one representation may be commonly used. For example, the Rupee could be typed as Rs, , रु. or some other symbol. Conversely, one symbol may ambiguously be used for more than one currency: if an Indonesian user typed the dollar symbol $, would he mean the Australian dollar, the US dollar, or something else? If possible, make your user pick the currency from a list (for example, through a drop-down list UI control) and only input the value as an ordinary number. Alternately, for applications processing many international currencies, consider the use of ISO 4217 codes, which can be reliably parsed and identified.
 

 
Formatting dates and times

Civilizations have been tracking time for millennia and several calendars are still in use today. As for numbers, the written representation of dates and times varies greatly across cultures. Fortunately, with help from the DateTimeFormatter class, your application can easily display them in a manner familiar to most users.
 
 
Culturally sensitive date and time formats
Calendar support varies widely across operating systems. At this time, only the Gregorian calendar is fully supported by the flash.globalization package.
 
Each order of magnitude (year, month, day) can be represented in different ways: with a full name, an abbreviation or a number (zero-padded or not). Those are choices dictated by circumstances. However, they are further complicated by cultural preferences.
 
Month names and weekday names must naturally be translated into the user's language. But using an all-numeric format will not save you from having to mind the locale.
 
For example, consider the date of the seventh of August in the year 2009 (see Table 3). An American user will typically write the month first, followed by the day and then the year. By contrast, a British user will generally write the day first, month next, and year last. A Canadian civil servant and a Japanese user will write the year, followed by the month and finally the day. Obviously, if the convention used is different from what the user expects, serious confusion is likely to ensue!
 
Examples of date and time formats
Table 3. Example of date formats
The written representation of the time of day is also subject to some variation, the most obvious being the use of a 24- or 12-hour clock. In the latter case, the half-day is indicated by an abbreviation (for example, AM or PM) that also varies from one language to another.
 
The formatter is able to represent dates and times in three standard formats (LONG, MEDIUM, and SHORT) and it can also use a CUSTOM pattern. The actual patterns used for each stock format may vary somewhat with the operating system. By contrast, custom patterns give you full control of the format, but remember that using them will prevent the formatter from automatically selecting a pattern that fits the selected locale (and therefore, the user). Table 4 shows an example of results that you might obtain.
 
Examples of date and time formats
Table 4. Examples of date and time formats
 
Neutrality persists better
Just as for numbers and monetary amounts, it is wise to use the most neutral representation possible when storing calendar values persistently (in a database or a file). Reserve the use of the date and time formatter to those situations when the application is directly interacting with the user. If you must store a textual representation, consider using methods toString() or toUTCString() of class Date, which outputs a textual representation based on the asctime() function of ANSI C. You can later use Date's parse() method to convert the text back into a Date object. Alternately, you might prefer (or need) to create your own formatter and parser functions to use, for example, a profile of ISO 8601 such as the one described in the Date and Time Formats note from the W3 Consortium.
 
When considering interoperability, do not forget that time zones and Daylight Saving Time also come into play. If your goal is to mark a document or event (for example, a transmission) with a timestamp that can later be compared, UTC time is generally preferable. If the local time (as seen on clocks by people) is important, it should also be stored, along with an indication of the time zone used. For example, the computed UTC time of a future event scheduled in local time may turn to be incorrect if the rules for Daylight Saving Time are changed.
 
 
Using the DateTimeFormatter class
As with numbers and dates, you begin by creating the formatter—this time by instantiating the class DateTimeFormatter. Specify a locale identifier or use the default locale:
 
import flash.globalization; var dateFormatter:DateTimeFormatter = new DateTimeFormatter(selectedLocale);
Here again, a fallback locale may have been selected. Read more about this in the discussion about class NumberFormatter and in the section, "Selecting a locale."
 
By default, the long date and time format will be selected. You can override this by passing additional arguments to the constructor or, at any time, by using the setDateTimeStyle() method:
 
// Set the formatter to show just the date (no time), in medium style. dateFormatter.setDateTimeStyle(DateTimeStyle.MEDIUM, DateTimeStyle.NONE);
Rather than changing the configuration of the formatter every time, consider instantiating several formatters that you configure once and reuse many times:
 
var dateFormatter:DateTimeFormatter = new DateTimeFormatter(selectedLocale, DateTimeStyle.MEDIUM, DateTimeStyle.NONE); var timeFormatter:DateTimeFormatter = new DateTimeFormatter(selectedLocale, DateTimeStyle.NONE, DateTimeStyle.MEDIUM);
You are now ready to format your first date:
 
var now:Date = new Date(); var todayText:String = dateFormatter.format(now);
The date and time formatter will automatically use month names and weekday names that are translated for the language specified through the locale identifier. Depending on the platform, when the pattern places the day adjacent to the month name, the latter's genitive form will automatically be used for languages that require it (Russian, Polish, Greek, etc.) For example, notice how Май (the Russian word for the month of May) adopts the genitive form мая as in "5th of May 2009" (see Figure 3).
 
Genitive month names
Figure 3. Genitive month names
If you need to draw a custom calendar, you can obtain those translated names from the formatter, using the methods getMonthNames() and getWeekdayNames(). Depending on the operating system, full names and abbreviated forms may be available (select the one you need with the constants from the DateTimeNameStyle class). Request the DateTimeNameContext.FORMAT form if you intend to use month names in conjunction with the day of the month (the genitive form will be returned if it exists), and the DateTimeNameContext.STANDALONE form if you intend to display them by themselves (for example, to form the title of a page in a monthly calendar). Additionally, the getFirstWeekday() method will return the identifier of the day traditionally marking the beginning of the week in the selected locale.
 
 
Customizing the date and time formatter
The date and time formatter provides a convenient way to pick and mix from four date formats and four time formats. If you desire something different, however, you can directly change the pattern (or template) used by the formatter. Are you wondering what the stock patterns look like? Simply retrieve them with the getDateTimePattern() method.
 
The real excitement, however, lies in the setDateTimePattern() method, which takes a simple text string describing what the output should look like. There is little sense in duplicating the reference manual here, but here is a straightforward example:
 
// Note: The following pattern is localizable (not the letters themselves, // but the format pattern expressed with them)! const datePattern:String = "yyyy-MM-dd (EEE)"; // Pattern is localizable! dateFormatter.setDateTimePattern(datePattern); var now:Date = new Date(); var todayText:String = dateFormatter.format(now);
Using an English locale, this example will output something that looks like this: 2009-08-17 (Mon). Note, however, that the exact result may slightly vary with the operating system.
 
If your application provides the user with a way to set personal preferences, you can now create different settings for long and short date or time formats and let each user modify them to his or her heart's content.
 
If you are instead planning to specify custom patterns in the application's code, keep in mind that, unless you have special needs, format patterns are likely to be localizable (that is, they will probably have to be changed to suit users in different locales). You should therefore externalize them, like the text strings used in the user interface, so that your translators can adapt them as needed. And, in all cases, it would be wise to give users a way to override your choice.
 
As much as possible, just stick to using the stock formats provided by the DateTimeFormatter class: after all, it is there to do the work of automatically selecting the right adaptation on the fly.
 

 
Comparing and sorting

Collation is the process of comparing elements to determine if they are equivalent or if one should logically follow the other. When applied to text, collation is particularly useful in two situations:
 
  • When you need to determine whether two pieces of text are equivalent enough to warrant returning one when the other is searched, or to avoid illegal duplicates in a database
  • When you need to order words or sentences in a collection that will be browsed by your users, so that they can quickly navigate to the item that they want to select
 
Culturally sensitive collation
The practice of ordering letters, words, and sentences is essential for catalogs, dictionaries, directories (for example, telephone books), list boxes or drop-down lists, and many other purposes. Ordering rules are directly tied to the writing system used and vary subtly or greatly across regions.
 
Several writing systems have common classes of equivalence. For example, European alphabets commonly treat majuscules (capital letters such as A, B, C, etc.) and corresponding minuscules (lowercase letters such as a, b, c, etc.) as largely equivalent and therefore kept together in ordered lists. In French, although diacritical marks (such as the circumflex accent in ê) are orthographically (and sometimes phonemically) relevant, they are given little weight during collation (so that ê, é, è, and ë are considered as mostly equivalent to the plain letter e). In Japanese, one might similarly choose to treat Hiragana (あ, い, う, etc.) and Katakana (ア, イ, ウ, etc.) characters as mostly equivalent.
 
One character may also represent different sounds or have different functions across different languages, and that is likely to affect its position in the collation order. For example, ö (the letter o with a dieresis) is considered mostly equivalent to the plain letter o in French or English, but deemed to follow the letter z in Swedish.
 
Finally, even within a community, special ordering may be used for different situations. In Germany, telephone directories have traditionally treated characters with an umlaut (such as ö) as being equivalent to the plain letter immediately followed by the letter e (as in oe). German dictionaries, however, do not use such equivalences. In Japan, a dictionary might use a word order based on pronunciation, or on radicals (graphical patterns appearing in many characters) and brush strokes, or even on semantic values (grouping words of similar meaning).
 
When ordering a list that will be presented visually to the user, it is essential to follow the user's expectations. It is not just a question of aesthetics: expecting it at the end of the list, a Swedish user might entirely fail to find an element that begins with ö if placed next to the plain o! Fortunately, avoiding that problem is easy: sort the list with a flash.globalization collator configured for the user's locale.
 
 
Matching versus searching
Being clear about your objectives is essential to using a collator properly: are you trying to determine whether you have a match between a pattern and a candidate, or are you building an ordered list of elements that will be displayed to the user?
 
Matching is typically performed when the user searches an item (for example, searching for a word in a document). When matching, you may want to ignore minor differences to increase the chances of finding relevant matches. For example, capitalization is commonly ignored. Diacritical marks are also often disregarded because not all users enter them as expected (either because their keyboard layout makes it difficult, or as the result of a spelling mistake). A number of Latin and Japanese characters also exist in half-width and full-width forms. This is not a matter of display style (font or other visual properties): rather, each form has a different code point (numeric value) in the character set. A Japanese user searching on "Hello リンリン" (half-width) most likely wants to find instances of "Hello リンリン" (full-width) also.
 
When sorting, on the other hand, unless you want to treat similar-looking entries as unwanted duplicates, each element from the input list will typically appear in the sorted list, and obtaining a predictable order (given a certain locale) requires the use of an algorithm that avoids equality as much as possible, handling any difference in a consistent manner. Capitalization may be given little weight, but it will still be taken into account.
 
The Collator class lets you choose which elements will be considered significant. To make things simpler, it also lets you specify a general mode of operation when you instantiate the collator: CollatorMode.MATCHING and CollatorMode.SORTING will configure all relevant settings of the collator in a way suitable for the desired type of operation.
 
 
Merits of staying neutral
As I discussed in the introduction, culturally sensitive operations only exist for the benefit of the human user. If you are considering collation for the purpose of speeding up database queries or avoiding duplicates in a primary key field, use a neutral collation order that is guaranteed to yield identical results on all platforms, forever. A simple binary comparison may be suitable for those purposes. In certain cases, you may need to normalize the text to avoid near-duplicates caused by graphically similar characters or by Unicode decomposed forms.
 
 
Using the Collator class
Once again, begin by creating the service object, this time an instance of class Collator. As always, you must specify a locale identifier.
 
As I explained earlier, you can (and should) also specify a general mode of operation: CollatorMode.SORTING (the default mode, ideal to build an ordered list that will be displayed to the user) or CollatorMode.MATCHING. (useful to match pieces of text that the user is likely to find equivalent, for example while searching):
 
import flash.globalization; var collator:Collator = new Collator(selectedLocale, CollatorMode.SORTING);
As with the formatters, if the platform does not fully support the locale that you specified, a fallback may have been selected. You can find out whether this happened by testing the lastOperationStatus property of class Collator immediately after creating the object. If it indicates anything other than LastOperationStatus.NO_ERROR, check the value of property actualLocaleIDName to find out which locale was used as fallback. Fallback is described in more detail in the section, "Selecting a locale."
 
You can now use one of the two main methods of the Collator class. If your intent is to order a list (the collator was instantiated for CollatorMode.SORTING), use the compare() method:
 
var comparisonResult:Integer = collator.compare("Hello リンリン","Hello リンリン"); if(comparisonResult < 0) { // The first string precedes the second. } else if(comparisonResult > 0) // The first string follows the second. } else { // comparisonResult is zero: both strings are considered identical. }
If you are only trying to find out whether you have a match (the collator was instantiated for CollatorMode.MATCHING), you can simply use the equals() method, which returns a Boolean value:
 
var matchResult:Boolean = collator.equals("Hello リンリン","Hello リンリン"); if(matchResult) { // Both strings are considered identical. } else { // No match. }
 
Customizing the collator
You can fine-tune the behavior of the collator by setting several of its properties. For example, set it to ignore capitalization differences (setting the ignoreCase property to true) and yet treat diacritical marks as a differentiating factor (setting the ignoreDiacritics property to false). Exposing those settings in the user interface of your application will enable users to adjust them to their liking when starting a search. Otherwise, the safe approach is simply to rely on the collation mode (specified when instantiating the collator) to configure the collator in a suitable way.
 
The numericComparison property is an interesting exception to this rule. Setting it to true causes the collator to take into account the numeric value of numbers embedded in the text rather than their textual representation. For example:
 
collator.numericComparison = true; var numericComparisonResult:Integer = collator.compare("Hello 10","Hello 2"); collator.numericComparison = false; var textualComparisonResult:Integer = collator.compare("Hello 10","Hello 2");
In the example above, numericComparisonResult will receive a positive value indicating that "Hello 10" follows "Hello 2", given that the numeric value 10 is greater than 2. By contrast, textualComparisonResult will receive a negative value indicating that "Hello 10" precedes "Hello 2", given that the character "1" precedes the character "2" in the collation order.
 
Once again, keep in mind that different operating systems may implement this functionality differently, particularly in regard to whether or not they can handle fractional or negative values and various families of numerals.
 

 
Transforming text

The flash.globalization package provides methods to convert letters to minuscules (lowercase letters) or majuscules (uppercase letters) for languages based on writing systems that incorporate the concept of capitalization (essentially, the Armenian, Latin, Cyrillic, and Greek alphabets). Using the StringTools class enables your application to use language-specific rules to perform those transformations.
 
 
Culturally sensitive transformations
The Latin alphabet is used to write many languages. Most national alphabets derived from it have added new letters (like the letter W or the German ß) and diacritical marks (such as the tittle, the circumflex accent, or the Germanic umlaut). Unsurprisingly, this also leads to language-specific rules whenever text must be converted from one form to another; for example, through capitalization.
 
A classic example is the letter I. Conceived to improve legibility, the tittle (the dot above) is a relatively modern addition to the minuscule form of the letter i. However, a few languages (Turkish, Azeri, and also Kazakh when written with the Latin alphabet) treat the dotless and the dotted variants as different letters, each with minuscule (ı and i) and majuscule (I and İ ) forms.
 
Figure 4 shows how the dotless majuscule I should thus be converted to the dotted minuscule i for Italian text, but to the dotless form ı for Turkish text. Conversely, the dotted minuscule i is converted into a dotless majuscule I in Italian but to the dotted form İ in Turkish.
 
Transformation of dotted and dotless letter I
Figure 4. Transformation of dotted and dotless letter I
Because class StringTools lets you specify the locale, it will generally produce correct results.
 
However, use such transformations with caution because they are often subject to additional rules that operating systems may fail to implement. In Greek, when converted to minuscule, the majuscule letter sigma, Σ, generally becomes σ, except at the end of words where it is written as ς. In German, the particle von denoting nobility in family names is not capitalized unless it begins a sentence; systematically capitalizing family names such as "von Goethe" could therefore produce incorrect results. In Dutch, the short form of the Dutch word het ('t) is never capitalized; if it appears at the beginning of a sentence, the next word is capitalized instead: 't Kofschip (ook wel 't fokschaap) is een bekend ezelsbruggetje.
 
Note: In many languages, text written entirely in majuscule (ALL CAPS or small caps) is considered bad form.
 
In short, try to avoid automatic text transformations as much as possible. It is often better to trust your user's input and leave it unchanged.
 
 
Using the StringTools class
As with formatters, you begin by creating an instance of the StringTools class, providing the identifier of the locale applicable to the text that you want to process or the locale preferred by the user:
 
import flash.globalization; var textToolset:StringTools = new StringTools(selectedLocale);
As always, a fallback locale may have been selected. For more about this, see the discussion of the NumberFormatter class in the section, "Selecting a locale."
 
Transforming text is now trivial: simply call the method toLowerCase() or toUpperCase():
 
var minuscules:String = textToolset.toLowerCase("MAJUSCULES"); var majuscules:String = textToolset.toUpperCase("minuscules");
Testing for possible errors is advised. If a critical error occurs, the transformation method could return an empty text string. You could then simply forfeit the transformation and use the original text string, though this obviously depends on your application. For example:
 
var originalText:String = "Sample text"; var capitalizedText:String; capitalizedText = textToolset.toUpperCase(originalText); if(textToolset.lastOperationStatus != LastOperationStatus.NO_ERROR) { capitalizedText = originalText; } // Go on using the value stored in 'capitalizedText'.

 
Where to go from here

The flash.globalization package enables your application to take advantage of the cultural support provided by the underlying platforms, providing a better experience to each user. For more details, refer to the flash.globalization package's API documentation.
 
A date formatted according to an Arabic locale could contain Arabic text (month or weekday names). To correctly present the results in the user interface, consider using the new Text Layout Framework, which properly handles bi-directional text. For more on the new text engine, visit the Text Layout Framework Technology Center.
 
To learn more about cultural conventions and locale identifiers, read about the CLDR and see how ICU puts it to use:
 
Finally, because the flash.globalization package relies on the underlying operating system, you may also find it useful to refer to platform documentation:
 
 
Microsoft Windows
 
Apple Mac OS X