Getting Started

This guide helps you set up a new l10ns project. We currently only support Javascript. Though in the future you will hopefully see wider support for more programming languages.

Install l10ns:

$ npm install l10ns -g

Create a new project folder test and initialize a new translation project. The initialization process will guide you through creating a project.

$ mkdir test
$ cd test
$ l10ns init

Now, create a source file test.js with (at least) the following code:

var requireLocalizations = require('path/to/output/all.js');
var l = requireLocalizations('en-US');
var firstname = l('SIGN_UP->FIRSTNAME');
var lastname = l('SIGN_UP->LASTNAME');

Now, lets update translation keys from source. It will traverse your source code and look for all l() calls:

$ l10ns update

Lets check which translation keys have been added:

$ l10ns log
@1 SIGN_UP->FIRSTNAME | NO TRANSLATION
@2 SIGN_UP->LASTNAME | NO TRANSLATION

Edit the last translation using log reference:

$ l10ns set @1 "Firstname" # using default langague
$ l10ns set @1 -l zh-CN "名" # using chinese

The new localization strings are now saved. Compile your localization strings using the following command:

$ l10ns compile

Lets set up a web interface for translators to use:

$ l10ns interface

Developer

Import

The outputted code from L10ns lets you import it with CommonJS and AMD.

var requireLocalizations = require('path/to/output/all.js');

You can also simply import it with HTML script tag.

<script type="text/javascript" src="path/to/output/all.js"></script>

For usage just require the locale you need and set it to the variable l. It is very important that you set it to the variable l. Because that is used for parsing your source code later on to update your translation keys.

var l = requireLocalizations('en-US');

You can also simply require each locale directly. And there will be no need to call requireLocalizations().

var l = require('/path/to/output/en-US');

Or if you are in a browser:

<script type="text/javascript" src="path/to/output/en-US.js"></script>

For express servers, we recommend use the middleware request-language.

var localizations = require('path/to/l10ns/output/all');

app.use(requestLanguage({
  languages: ['en-US', 'zh-CN'],
  cookie: {
    name: 'language',
    options: { maxAge: 24*3600*1000 },
    url: '/languages/{language}'
  },
  localizations: localizations
});

And after setting the middleware you can just use your localizations by setting a local variable l from request.localizations. Notice, if you are not setting this local variable L10ns will not be able to extract it with l10ns update.

app.get(function(req, res, next) {
  var l = req.localizations;
});

Usage

L10ns provides a simple getter l for getting your localized strings.

l('TRANSLATION_KEY'[, Data]);

Example usage of a simple getter:

l('SIGN_UP->FIRSTNAME');

Example usage of a more complex getter:

l('FEED->COMMENTS', {
  gender: 'male',
  comments: 100
});

Just run l10ns update in your terminal. And it will extract all the translation keys and all the defined variables.

Naming keys

We recommend to set your translation keys with capital letters. And namespace it with a content type as the first part of the key. And the other part should be a name describing the string. Use the arrow characters -> for namespacing.

l('CONTENT_TYPE->STRING_NAME');

You need to namespace the translation keys, because some times the same string name can be used on different content. For example: a header for a document has the translation key HEADER, which is used in more than one place might have different localized strings on different pages. To solve this problem use a content type as a prefix namespace. If there exists a header for a login page, use LOGIN->HEADER as a translation key. If there exists a header for a sign up page, use SIGN_UP->HEADER as a translation key.

For those strings that spans multiple content types. We recommend namespace them with DEFAULT.

l('DEFAULT->CANCEL');

Do not use normal spoken English sentences as translation keys. We do not recommend this because it contain no namespaces. And it is bad for maintenance since if you want to change a string you need to change the translation key too.

Example of a bad translation key:

l('Hide this button');

Some times, the same English word can be translated differently depending on context. So translators need some information on which view a text belongs to. By naming your localization key by including the view hiearchy — the translators can easily figure out which view a text belongs to. Please tell your translators also to use our built-in translation interface l10ns interface. We will present them the English text there. The English text and the view context is all the information a translator need to translate any kind of text.

Message Format

Messageformat is Domain Specific Language(DSL) for handling localization. It was invented by the guys who invented Unicode. Messageformat is the most effective solution today for localizing strings. It uses a markup that can be inlined in a string to pluralize words or make words respond to different genus context etc.

Interpolation

In Message Format define interpolation variables using the syntax:

{variable}

Interpolation takes a string or a number as an argument.

l('TRANSLATION_KEY', {
  user1: 'Emma',
  user2: 'Albert'
});

Example of usage:

{user1} likes {user2}.

If user1 is Emma and user2 is Albert. The output will be:

Emma likes Albert.

Select Format

Select Format is primarily used for localizing genus context based message. But it can also be used for different kind of applications other than genus context based messages. Select Format takes a variable as an argument and the translator needs to define a set of cases and corresponding values for each case. The syntax for Select Format is:

{variable, select, case-1{message-1}...case-n{message-n} other{message-other}}

Select Format takes a string as an argument.

l('TRANSLATION_KEY', {
  gender: 'male'
});

And it can be used for translating messages based on genus context:

{gender, select, male{He} other{She}} likes the L10ns project.

If gender equals male. The output will be:

He likes the L10ns project.

And If gender equals female. The output will be:

She likes the L10ns project.

Plural Format

Plural Format is used for formatting messages based on different plural forms. The plural forms for each locale is defined by CLDR(Common Locale Data Repository). CLDR is a repository where many organization and companies participate for gathering locale specific data. CLDR currently defines 6 different kinds of plural forms, zero, one, two, few, many and other. Each plural form and the number of plural form may be different from locale to locale. For the English language there exists only two plural forms one and other. The Chinese language have only one plural form other. The Arabic language have 6 plural forms zero, one, two, few, many and other. Example numbers of each plural form will be provided if you translate your strings using the translation interface.

{variable, plural, plural-form-1{message-1}...plural-form-n{messane-n} other{message-other}}

Plural Format takes a number as an argument.

l('TRANSLATION_KEY', {
  comments: 3
});

Example usage for English:

He likes {comments, plural, one{# comment} other{# comments}}.

If comments equals 1. The output will be:

He likes 1 comment.

If comments equals 1000. The output will be:

He likes 1,000 comments.

In the above examples we use the # to interpolate the message with a count. The displayed count will always be formated to an integer using L10ns Number Format, thus the number separator ,.

We can also specify exact cases. Instead of using the plural forms. Notice: the plural form one is a name of a plural form. It doesn't exactly means the number one. In some languages the plural form one includes the number zero too. You specify an exact case by n=. Here is an example of a Plural Format with exact cases:

There {files, plural, =0{are no files} one{is one file} other{are many files}}.

Some times we want to interpolate a message with a count with an offset using offset:n:

{people, plural, offset:1 =0{No one went.} =1{{user1} went.} =2{{user1} and {user2} went}.} other{{user1} and # others went}}.

If you would have translated the above message in Arabic. You might want to use more plural forms than other. Because the word others have many plural forms. As a rule of thumb, always use the exact cases before the plural form cases!

Selectordinal Format

Selectordinal Format is used for formating messages with different ordinal forms. CLDR defines six types of ordinal forms zero, one, two, few, many and other. Each ordinal form and the number of ordinal forms may be different from locale to locale. In the English language there exists four ordinal forms one, two, few and other for formatting messages including first, second, third and fourth etc. And the ordinal form one doesn't necessarily corresponds to the number one. Sometimes the ordinal form one might corresponds to the number 1, 2 and more, such as in the Swedish language. Same thing applies to all the ordinal forms. Example numbers of each ordinal form will be provided if you translate your strings using the translation interface.

The syntax for Selectordinal Format is:

{variable, selectordinal, ordinal-form-1{message-1} ordinal-form-n{message-n} other{message-other}}

Selectordinal Format takes a number as an argument.

l('TRANSLATION_KEY', {
  floor: 3
});

An example usage of Selectordinal Format:

Go to the {floor, selectordinal, =0{ground} one{#st} two{#nd} few{#rd} other{#th}} floor.

The characters # and =n is used for specifying a number formated count and exact cases. And they work exactly the same as in Plural Format.

Number Format

The syntax for Number Format is:

{variable, number, argument}

Argument in above can take the values integer, percent, permille or a decimal pattern. A decimal pattern is described in next section.

Number Format takes a number as an argument.

l('TRANSLATION_KEY', {
  price: 1000
});

If your number format contains a decimal pattern with a currency symbol ¤, then Number Format takes a Javascript object containing properties code and amount as an argument. Code must be an ISO 4217 currency code and amount must be of type number.

l('TRANSLATION_KEY', {
  price: {
    code: 'USD',
    amount: 1000
  }
});

An example for formatting integer:

{variable, number, integer}

An example for formatting percentage:

{variable, number, percent}

An example for formatting a custom pattern:

{variable, number, #,##0.00}

Please see the next section for decimal pattern for customizing your number formatting.

Decimal pattern

The characters listed here are used in non-localized patterns. Localized patterns use the corresponding characters. Two exceptions are the currency sign and quote, which are not localized.

Symbol Location Localized Description
0 Number Yes Digit.
1-9 Number Yes 1 through 9 indicate rounding.
@ Number No Significant digit.
# Number Yes Digit, zero shows as absent.
. Number Yes Decimal separator or monetary decimal separator.
- Number Yes Minus sign.
, Number Yes Grouping separator.
E Number Yes Separates mantissa and exponent in scientific notation. Need not be quoted in prefix or suffix.
+ Exponent Yes Prefix positive exponents with localized plus sign. Need not be quoted in prefix or suffix.
; Subpattern boundary Yes Separates positive and negative subpatterns.
% Prefix or suffix Yes Multiply by 100 and show as percentage.
Prefix or suffix Yes Multiply by 1000 and show as per mille.
¤ Prefix or suffix No One consecutive currency symbol will be replaced with a local symbol such as $. Two consecutive symbols will be replaced with a global symbol such as US$. Three consecutive symbols will be replaced with a local text such as dollars. Four consecutive symbols will be replaced with a global text such as US dollars. Please specify which currencies you are using in your configuration file l10ns.json. Please see currencyformat for more information.
' Prefix or suffix No Used to quote special characters in a prefix or suffix, for example, '#'# formats 123 to #123. To create a single quote itself, use two in a row: # o''clock.
* Prefix or suffix boundary Yes Pad escape, precedes pad character.

A decimal pattern pattern contains a postive and negative subpattern, for example, #,##0.00;(#,##0.00). Each subpattern has a prefix, a numeric part, and a suffix. If there is no explicit negative subpattern, the negative subpattern is the localized minus sign prefixed to the positive subpattern. That is, 0.00 alone is equivalent to 0.00;-0.00. If there is an explicit negative subpattern, it serves only to specify the negative prefix and suffix; the number of digits, minimal digits, and other characteristics are ignored in the negative subpattern. That means that #,##0.0#;(#) has precisely the same result as #,##0.0#;(#,##0.0#).

The grouping separator is a character that separates clusters of integer digits to make large numbers more legible. It commonly used for thousands, but in some locales it separates ten-thousands. The grouping size is the number of digits between the grouping separators, such as 3 for 100,000,000 or 4 for 1 0000 0000. There are actually two different grouping sizes: One used for the least significant integer digits, the primary grouping size, and one used for all others, the secondary grouping size. In most locales these are the same, but sometimes they are different. For example, if the primary grouping interval is 3, and the secondary is 2, then this corresponds to the pattern #,##,##0, and the number 123456789 is formatted as 12,34,56,789. If a pattern contains multiple grouping separators, the interval between the last one and the end of the integer defines the primary grouping size, and the interval between the last two defines the secondary grouping size. All others are ignored, so #,##,###,#### == ###,###,#### == ##,#,###,####.

pattern    := subpattern (';' subpattern)?
subpattern := prefix? number exponent? suffix?
number     := (integer ('.' fraction)?) | sigDigits
prefix     := '\u0000'..'\uFFFD' - specialCharacters
suffix     := '\u0000'..'\uFFFD' - specialCharacters
integer    := '#'* '0'* '0'
fraction   := '0'* '#'*
sigDigits  := '#'* '@' '@'* '#'*
exponent   := 'E' '+'? '0'* '0'
padSpec    := '*' padChar
padChar    := '\u0000'..'\uFFFD' - quote

Notation:
X* 0 or more instances of X
X? 0 or 1 instances of X
X|Y either X or Y
C..D any character from C up to D, inclusive
S-T characters in S, except those in T

The first subpattern is for positive numbers. The second (optional) subpattern is for negative numbers.

Not indicated in the BNF syntax above:

  • The grouping separator , can occur inside the integer and sigDigits elements, between any two pattern characters of that element, as long as the integer or sigDigits element is not followed by the exponent element.
  • Two grouping intervals are recognized: That between the decimal point and the first grouping symbol, and that between the first and second grouping symbols. These intervals are identical in most locales, but in some locales they differ. For example, the pattern #,##,### formats the number 123456789 as 12,34,56,789.
  • The pad specifier padSpec may appear before the prefix, after the prefix, before the suffix, after the suffix, or not at all.
  • In place of 0, the digits 1 through 9 may be used to indicate a rounding increment.

Formatting

Formatting is guided by several parameters, all of which can be specified either using a pattern or using the API. The following description applies to formats that do not use scientific notation or significant digits.

If the number of actual integer digits exceeds the maximum integer digits, then only the least significant digits are shown. For example, 1997 is formatted as 97 if the maximum integer digits is set to 2.

If the number of actual integer digits is less than the minimum integer digits, then leading zeros are added. For example, 1997 is formatted as 01997 if the minimum integer digits is set to 5.

If the number of actual fraction digits exceeds the maximum fraction digits, then rounding is performed to the maximum fraction digits. For example, 0.125 is formatted as 0.12 if the maximum fraction digits is 2. This behavior can be changed by specifying a rounding increment and/or a rounding mode.

If the number of actual fraction digits is less than the minimum fraction digits, then trailing zeros are added. For example, 0.125 is formatted as 0.1250 if the mimimum fraction digits is set to 4.

Trailing fractional zeros are not displayed if they occur j positions after the decimal, where j is less than the maximum fraction digits. For example, 0.10004 is formatted as 0.1 if the maximum fraction digits is four or less.

Special Values

NaN is represented as a single character, typically \uFFFD. This character is determined by CLDR. This is the only value for which the prefixes and suffixes are not used.

Infinity is represented as a single character, typically \u221E, with the positive or negative prefixes and suffixes applied. The infinity character is determined by CLDR.

Scientific Notation

Numbers in scientific notation are expressed as the product of a mantissa and a power of ten, for example, 1234 can be expressed as 1.234 x 103. The mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0), but it need not be. Number Format supports arbitrary mantissas. Number Format can be instructed to use scientific notation through the API or through the pattern. In a pattern, the exponent character immediately followed by one or more digit characters indicates scientific notation. Example: 0.###E0 formats the number 1234 as 1.234E3.

  • The number of digit characters after the exponent character gives the minimum exponent digit count. There is no maximum. Negative exponents are formatted using the localized minus sign, not the prefix and suffix from the pattern. This allows patterns such as 0.###E0 m/s. To prefix positive exponents with a localized plus sign, specify + between the exponent and the digits: 0.###E+0 will produce formats 1E+1, 1E+0, 1E-1, etc. (In localized patterns, use the localized plus sign rather than +).
  • The minimum number of integer digits is achieved by adjusting the exponent. Example: 0.00123 formatted with 00.###E0 yields 12.3E-4. This only happens if there is no maximum number of integer digits. If there is a maximum, then the minimum number of integer digits is fixed at one.
  • The maximum number of integer digits, if present, specifies the exponent grouping. The most common use of this is to generate engineering notation, in which the exponent is a multiple of three, e.g., ##0.###E0. The number 12345 is formatted using ##0.####E0 as 12.345E3.
  • When using scientific notation, the formatter controls the digit counts using significant digits logic. The maximum number of significant digits limits the total number of integer and fraction digits that will be shown in the mantissa; it does not affect parsing. For example, 12345 formatted with ##0.##E0 is 12.3E3. See the section on significant digits for more details.
  • The number of significant digits shown is determined as follows: If a significant pattern is not used, then the minimum number of significant digits shown is one, and the maximum number of significant digits shown is the sum of the minimum integer and maximum fraction digits, and is unaffected by the maximum integer digits. If this sum is zero, then all significant digits are shown. If a significant pattern is used, then the significant digit counts are specified by minimum significant digits and maximum significant digits. In this case, the number of integer digits is fixed at one, and there is no exponent grouping.
  • Exponential patterns may not contain grouping separators.

Significant Digits

Number Format has two ways of controlling how many digits are shown: (a) significant digits counts, or (b) integer and fraction digit counts. Integer and fraction digit counts are described above. When a formatter is using significant digits counts, the number of integer and fraction digits is not specified directly, and the formatter settings for these counts are ignored. Instead, the formatter uses however many integer and fraction digits are required to display the specified number of significant digits. Examples:

Pattern Min. sign. digits Max. sign. digits Number Output
@@@ 3 3 12345 12300
@@@ 3 3 0.12345 0.123
@@## 2 4 3.14159 3.142
@@## 2 4 1.23004 1.23
  • Significant digit counts may be expressed using patterns that specify a minimum and maximum number of significant digits. These are indicated by the @ and # characters. The minimum number of significant digits is the number of @ characters. The maximum number of significant digits is the number of @ characters plus the number of # characters following on the right. For example, the pattern @@@ indicates exactly 3 significant digits. The pattern @## indicates from 1 to 3 significant digits. Trailing zero digits to the right of the decimal separator are suppressed after the minimum number of significant digits have been shown. For example, the pattern @## formats the number 0.1203 as 0.12.
  • If a pattern uses significant digits, it may not contain a decimal separator, nor the '0' pattern character. Patterns such as @00 or @.### are disallowed.
  • Any number of # characters may be prepended to the left of the leftmost @ character. These have no effect on the minimum and maximum significant digits counts, but may be used to position grouping separators. For example, #,#@# indicates a minimum of one significant digits, a maximum of two significant digits, and a grouping size of three.
  • In order to enable significant digits formatting, use a pattern containing the '@' pattern character.
  • In order to disable significant digits formatting, use a pattern that does not contain the @ pattern character.
  • The number of significant digits has no effect on parsing.
  • Significant digits may be used together with exponential notation. Such patterns are equivalent to a normal exponential pattern with a minimum and maximum integer digit count of one, a minimum fraction digit count of minimum significant digits minus 1, and a maximum fraction digit count of maximum significant digits minus 1. For example, the pattern @@###E0 is equivalent to 0.0###E0.

Padding

Number Format supports padding the result to a specific width. Padding may be specified either through the syntax. In a pattern the pad escape character, followed by a single pad character, causes padding to be parsed and formatted. The pad escape character is *. For example, $*x#,##0.00 formats 123 to $xx123.00, and 1234 to $1,234.00.

  • When padding is in effect, the width of the positive subpattern, including prefix and suffix, determines the format width. For example, in the pattern * #0 o''clock, the format width is 10.
  • The width is counted in 16-bit code units.
  • Some parameters which usually do not matter have meaning when padding is used, because the pattern width is significant with padding. In the pattern * ##,##,#,##0.##, the format width is 14. The initial characters ##,##, do not affect the grouping size or maximum integer digits, but they do affect the format width.
  • Padding may be inserted at one of four locations: before the prefix, after the prefix, before the suffix, or after the suffix. If there is no prefix, before the prefix and after the prefix are equivalent, likewise for the suffix.
  • When specified in a pattern, the 32-bit code point immediately following the pad escape is the pad character. This may be any character, including a special pattern character. That is, the pad escape escapes the following character. If there is no character after the pad escape, then the pattern is illegal.

Rounding

Number Format supports rounding to a specific increment. For example, 1230 rounded to the nearest 50 is 1250. 1.234 rounded to the nearest 0.65 is 1.3. To specify a rounding increment include the increment in the pattern itself. #,#50 specifies a rounding increment of 0.05.

  • Rounding only affects the string produced by formatting. It does not affect parsing or change any numerical values.
  • Some locales use rounding in their currency formats to reflect the smallest currency denomination.
  • In a pattern, digits 1 through 9 specify rounding, but otherwise behave identically to digit 0.

In the absense of an explicit rounding increment numbers are rounded to their formatted width.

Currency Format

Currency Format is just a short-hand function for formating currency amounts. It is used for formating different currency formats for different locales. If you don't use any complex formatting with your currency amount use Currency Format. If you are doing any kind of complex formating with currency units involved use Number Format.

{variable, currency, context, type}

Whenever you use currency formatting you need to specify what currencies you intend to use in your configuration file l10ns.json. The currency codes should conform to ISO 4217 http://en.wikipedia.org/wiki/ISO_4217.

{
  ...
  currencies: [
    "USD"
  ],
  ...
}

Currency Format takes a Javascript object containing properties code and amount as an argument. Code must be an ISO 4217 currency code and amount must be of type number.

l('TRANSLATION_KEY', {
  price: {
    code: 'USD',
    amount: 1000
  }
});

Context can take two values local or global. And type can also only takes two values symbol or text. We recommend using a local context if you are showing the currency amount to local people using a local language. Locale context in en-US will yield the symbol $ or the text dollar. In all other cases use a global context. A global context in en-US and global context will yield the symbol US$ or the text US dollar. For the French language, the currency symbol in a global context is usually before the region instead of after. So French people want to see $US instead of $US. For this use case we implemented a reverseglobal context.

Example usage for formating the currency amount $50.00 in the locale en-US:

{price, currency, local, symbol}

Example usage for formating the currency amount US$50.00 in the locale en-US:

{price, currency, global, symbol}

Example usage for formating the currency amount 50.00 dollars in the locale en-US:

{price, currency, local, text}

Example usage for formating the currency amount 50.00 US dollars in the locale en-US:

{price, currency, global, text}

Example usage for formating the currency amount $US 50.00 in the locale fr-CA:

{price, currency, reverseglobal, symbol}

Having the opportunity to choose between using text or symbol is especially useful in Chinese and Japanese. In the Chinese language, some websites use the currency symbol ¥, but because the character 元 is so short, it is more frequent to use the character 元 instead of the symbol ¥.

Notice 1: The default currency amounts for USD in locale en-US have two fraction digits and it is defined in CLDR. Some website don't want fractions because they only show integers. We recommend you to use Number Format for this use case.

Notice 2: Some website use to wrap the currency symbols with the html tags <sup> or <sub>. Use Number Format for this use case.

Date Format

Date Format is used for formatting date values. Date Format is very flexible and you can almost get any value you want in any format you want. It also supports time zones with data from IANA.

The syntax for defining a date format is:

{time, date, [date identifiers]}

If you are using timezones, you need to specify which timezones you supports in your configuration file l10ns.json. Please use an IANA timezone ID to specify which timezones you supports. A list if IANA timezone ID:s can be found here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones.

{
  ...
  timezones: [
    "America/Los_Angeles"
  ],
  ...
}

If we want to render into the format 2014-12-24 19:14, we would need to specify the markup:

{startTime, date, yyyy-MM-dd HH:mm}

If you want to use the above date format. You will need to pass in an a variable time of type Date.

l('TRANSLATION_KEY', {
  startTime: new Date()
});

If you want to render the date format in an another timezone. You need to pass in an object containing the property time of type Date and a property timezone which corresponds to an IANA timezone ID:

l('TRANSLATION_KEY', {
  startTime: {
    time: new Date(),
    timezone: 'America/Los_Angeles'
  }
});

Use these identifiers to construct your date formatted strings. Please notice that inlined and stand-alone in the English examples are mostly the same. Though in other languages they can produce different outputs. Inlined means that this identifier is used within a text and stand-alone means the identifier isn't used together with other text.

Field Symbol Consecutive Example Description
Era G 1..3 AD Era - Replaced with the Era string for the current date. One to three letters for the abbreviated form, four letters for the long (wide) form, five for the narrow form.
4 Anno Domini
5 A
Year y 1..n 1996 Year. Normally the length specifies the padding, but for two letters it also specifies the maximum length.
Y 1..n 1997 Year (in "Week of Year" based calendars). Normally the length specifies the padding, but for two letters it also specifies the maximum length. This year designation is used in ISO year-week calendar as defined by ISO 8601, but can be used in non-Gregorian based calendar systems where week date processing is desired. May not always be the same value as calendar year.
Quarter Q 1..2 02 Inlined quarter - Use one or two for the numerical quarter, three for the abbreviation, or four for the full (wide) name (five for the narrow name is not yet supported).
3 Q2
4 2nd quarter
q 1..2 02 Stand-alone quarter - Use one or two for the numerical quarter, three for the abbreviation, or four for the full name (five for the narrow name is not yet supported).
3 Q2
4 2nd quarter
Month M 1..2 09 Inlined month - Use one or two for the numerical month, three for the abbreviation, four for the full (wide) name, or five for the narrow name. With two ("MM"), the month number is zero-padded if necessary (e.g. "08")
3 Sep
4 September
5 S
L 1..2 09 Stand-alone month - Use one or two for the numerical month, three for the abbreviation, four for the full (wide) name, or 5 for the narrow name. With two ("LL"), the month number is zero-padded if necessary (e.g. "08")
3 Sep
4 September
5 S
Week w 1..2 27 Week of Year. Use "w" to show the minimum number of digits, or "ww" to always show two digits (zero-padding if necessary, e.g. "08").
W 1 3 Week of Month
Day d 1..2 1 Date - Day of the month. Use "d" to show the minimum number of digits, or "dd" to always show two digits (zero-padding if necessary, e.g. "08").
D 1..3 345 Day of year
F 1 2 Day of Week in Month. The example is for the 2nd Wed in July
Week Day e 1..2 2 Inlined day of week
3 Tue
4 Tuesday
5 T
6 Tu
c 1..2 2 Stand-alone day of week
3 Tue
4 Tuesday
5 T
6 Tu
Period a 1..3 AM Period of Day. Choose to format a period in an abbreviated format (AM/PM) using three period identifiers, a wide format (also AM/PM in English, but might be different in other languages) using four identifiers or a narrow format (a/p) using 5 identifiers.
4 AM
5 a
Hour h 1..2 11 Hour [1-12]. When used in skeleton data or in a skeleton passed in an API for flexible data pattern generation, it should match the 12-hour-cycle format preferred by the locale (h or K); it should not match a 24-hour-cycle format (H or k). Use hh for zero padding.
H 1..2 13 Hour [0-23]. When used in skeleton data or in a skeleton passed in an API for flexible data pattern generation, it should match the 24-hour-cycle format preferred by the locale (H or k); it should not match a 12-hour-cycle format (h or K). Use HH for zero padding.
K 1..2 0 Hour [0-11]. When used in a skeleton, only matches K or h, see above. Use KK for zero padding.
k 1..2 24 Hour [1-24]. When used in a skeleton, only matches k or H, see above. Use kk for zero padding.
Minute m 1..2 59 Minute. Use "m" to show the minimum number of digits, or "mm" to always show two digits (zero-padding if necessary, e.g. "08").
Second s 1..2 12 Second. Use "s" to show the minimum number of digits, or "ss" to always show two digits (zero-padding if necessary, e.g. "08").
S 1..n 3450 Fractional Second - truncates (like other time fields) to the count of letters when formatting. Appends zeros if more than 3 letters specified. Truncates at three significant digits when parsing. (example shows display using pattern SSSS for seconds value 12.34567).
Timezone z 1..3 PDT The short specific non-location format. Where that is unavailable, falls back to the short localized GMT format ("O").
4 Pacific Daylight Time The long specific non-location format. Where that is unavailable, falls back to the long localized GMT format ("OOOO").
Z 1..3 -0800 The ISO8601 basic format with hours and minutes. The format is equivalent to RFC 822 zone format. This is equivalent to the "xx" specifier.
4 GMT-08:00 The long localized GMT format. This is equivalent to the "OOOO" specifier.
5 -08:00
Z
The ISO8601 extended format with hours and minutes. The ISO8601 UTC indicator "Z" is used when local time offset is 0. This is equivalent to the "XXX" specifier.
O 1 GMT-8 The short localized GMT format.
4 GMT-08:00 The long localized GMT format.
v 1 PT The short generic non-location format. Where that is unavailable, falls back to the generic location format ("VVVV"), then the short localized GMT format as the final fallback.
4 Pacific Time The long generic non-location format. Where that is unavailable, falls back to generic location format ("VVVV"), then the long localized GMT format as the final fallback.
V 1 America/
Los_Angeles
The long time zone ID.
2 Los Angeles The exemplar city (location) for the time zone. Where that is unavailable, the localized exemplar city name for the special zone Etc/Unknown is used as the fallback (for example, "Unknown City").
3 Los Angeles Time The generic location format. Where that is unavailable, falls back to the long localized GMT format ("OOOO"; Note: Fallback is only necessary with a GMT-style Time Zone ID, like Etc/GMT-830.) This is especially useful when presenting possible timezone choices for user selection, since the naming is more uniform than the "v" format.
x 1 -08
+0530
The ISO8601 basic format with hours field and optional minutes field.
2 -0800 The ISO8601 basic format with hours and minutes fields.
3 -08:00 The ISO8601 extended format with hours and minutes fields.
X 1 -08
+0530
Z
The ISO8601 basic format with hours field and optional minutes field. The ISO8601 UTC indicator "Z" is used when local time offset is 0.
2 -0800
Z
The ISO8601 basic format with hours and minutes fields. The ISO8601 UTC indicator "Z" is used when local time offset is 0.
3 -08:00
Z
The ISO8601 extended format with hours and minutes fields. The ISO8601 UTC indicator "Z" is used when local time offset is 0.