If the shell escape is enabled or \directlua is available, this package may also be used to query the LC_ALL or LANG environment variable (see §6). Windows users, who don’t have the locale stored in environment variables, can use texosquery in combination with tracklang. (Similarly if LC_ALL or LANG don’t contain sufficient information.) In order to use texosquery through the restricted shell escape, you must have at least Java 8 and set up texosquery.cfg appropriately. (See the texosquery manual for further details.) 
The fundamental aim of this generic package is to be able to effectively say:
The user (that is, the document author) wants to use dialectsNaturally, this is only of use if the locale-sensitive packages use tracklang to pick up this information, which is entirely up to the package authors, but at the moment there’s no standard method for packages to detect the required language and region. The aim of tracklang is to provide that method. In particular, the emphasis is on using ISO language and region codes rather than hard-coding the various language labels used by different language packages.xx-XX,yy-YY-Scrp, etc in their document. Any packages used by their document that provide multilingual or region-dependent support should do whatever is required to activate the settings for those languages and regions (or warn the user that there’s no support).
Related articles: “Localisation of TeX documents: tracklang.” TUGboat, Volume 37 (2016), No. 3, Localisation with tracklang.tex, and tracklang FAQ.
 
 
 
When I’m developing a package that provides multilingual support (for example, glossaries) it’s cumbersome trying to work out if the user has requested translations for fixed text. This usually involves checking if babel or translator or polyglossia has been loaded and, if so, what language settings have been used. The result can be a tangled mass of conditional code. The alternative is to tell users to add the language as a document class option, which they may or may not want to do, or to tell them to supply the language settings to every package they load that provides multilingual support, which users are even less likely to want to do. 
The tracklang package tries to neaten this up by working out as much of this information as possible for you and providing a command that iterates through the loaded languages. This way, you can just iterate through the list of tracked languages and, for each language, either define the translations or warn the user that there’s no translation for that language. 
This package works best with ngerman and german (since it’s a simple test to determine if they have been loaded) and recent versions of polyglossia (which conveniently provides  
Unfortunately I can’t find any way of detecting a list of languages loaded through babel’s new  
If the ngerman package has been loaded, tracklang effectively does:  
If any document class or package options are passed to tracklang, then tracklang won’t bother checking for babel, translator, ngerman, german or polyglossia. So, if the above example is changed to:  
Predefined dialects are listed in Tables 1.1, 1.2 & 1.3. These may be  passed in the document class options or used in  
§2 provides brief examples of use for those who want a general overview before reading the more detailed sections. §3 describes generic commands for identifying the document languages. §5 is for package writers who want to add multilingual support to their package and need to know which settings the user has requested through language packages like babel. §6 is for developers of language definition packages who want to help other package writers to detect what languages have been requested. 
 
 
 
 
There are three levels of use: 
 
 
 
 
Document level use can be divided into generic TeX use  (§2.1.1) and LaTeX-specific use (§2.1.2). 
 
This section is for generic TeX use. The tracklang files are loaded with  
A Unix-like user wants the locale information picked up from the  locale environment variable (the tex extension may be omitted):  
A Windows user wants the locale information picked up from the  operating system (again the tex extension may be omitted):  
A user is writing in Italy in Armenian with a Latin script (Latn) and the arevela variant:  
A user is writing in English in the UK:  
Find out information about the current language (supplied in  
 
This section is for LaTeX use. See §2.1.1 for generic TeX use. 
With newer versions of polyglossia, where  
For babel users where the supplied babel dialect label is sufficient, and is passed either through the document class or package options, there’s no need to do anything special:  
Another method with babel is to use  
There’s no support for  
 
Let’s suppose you are developing a package called  mypackage.sty or mypackage.tex and you want to find out what languages the document author has requested. (See also: Using tracklang.tex in Packages with Localisation Features.) 
Generic TeX use (the tex extension may be omitted):  
LaTeX use:  
(LaTeX) If you want to allow the user to set the locale in the  package options:  
 
If you want to fetch the locale information from the operating system when the user hasn’t requested a language:  
Set up the defaults if necessary:  
Now load the resource files:  
Each resource file has the naming scheme -.ldf. In this example, the  is mypackage. The  part may be the language or dialect label (for example, english or british) or a combination of the ISO language and region codes (for example, en-GB or en or GB). As from version 1.4,  may also include the script or variant. (See the definition of  
The simplest scheme is to use the root language label (not the dialect label) for the base language settings and use the ISO codes for regional support. 
For example, the file mypackage-english.ldf:  
With pre-v1.4 versions of tracklang, the script isn’t included in the file search. If it’s needed then either require at least v1.4 or have a base ldf file that tries to load a version for the particular script (which can be accessed with  
 
Let’s suppose now you’re the developer of a package that  sets up the language, hyphenation patterns and so on. It would be really helpful to the locale-sensitive packages  in §2.2 to know what languages the document author has requested. You can use the tracklang package to identify this information by tracking the requested localisation, so that other packages can have a consistent way of querying it. (See also: Integrating tracklang.tex into Language Packages.) 
Generic use:  
When a user requests a particular language through your package, the simplest way of letting tracklang know about it is to use  
This now means that  
When the user switches language through commands like  
 
For plain TeX you can input tracklang.tex:  
The LaTeX package tracklang.sty  inputs the generic TeX code in tracklang.tex, but before  it does so it defines  
This means that all the predefined languages and dialects (Tables 1.1, 1.2 & 1.3) automatically become package options, so the tracklang.sty package can pick up document class options and add them to tracklang’s internal list of tracked document languages. 
If you’re not using LaTeX, this option isn’t available although you can redefine   
 
For example:  
Note that it’s impractical to define every possible language and region combination as it would significantly slow the time taken to load tracklang so, after version 1.3, I don’t intend adding any new predefined dialects. As from version 1.3, if you want to track a dialect that’s not predefined by tracklang, then you can use:  
For example:  
 
Alternatively, you can use  
If you want to first check that  includes a valid language code, then you can instead use:  
For example:  
The datetime2 package assumes that any unknown package option is a language identifier. It could simply do:  
If  contains a sub-language tag, this will be set as the 639-3 code for the dialect label. Note that this is different to the root language codes which are set using the language label. For example:  
Version 1.2 of texosquery provides the command  
Some of the predefined root language options listed in Table 1.2 have an associated region (denoted by †). If  
(New to version 1.3.) There’s a similar command to  
Since tracklang is neither able to look up the POSIX locale tables nor interpret file locales, if the result is  
 
If the operating system locale can’t be obtained from environment variables, then tracklang will use  
Plain TeX example:  
LaTeX example:  
If the locale can’t be determined, there will be warning messages. These can be suppressed using  
For example, I have the environment variable  
With LaTeX documents I can do  
The  
If the command:  
 
For example:  
If the shell escape is unavailable  (for example, your TeX installation prohibits it), you can set this value when you invoke TeX. For example, if the document file is called myDoc.tex (and it’s in Plain TeX):  
The  
The language code is stored in:  
The territory (if present) is stored in:  
The code-set (if present) is stored in:  
The modifier (if present) is stored in:  
If you want to query the language environment, but don’t want to track the result, you can just use:  
The above queries  
Since this sets  
It’s also possible to just parse the value of  
Example (Plain TeX):  
Compare this with:  
 
If  
For example, tracklang doesn’t recognise  
 
In addition to the main tracklang.tex file and tracklang.sty LaTeX wrapper, the tracklang package also provides supplementary files for region and script mappings. 
 
 
 
 
 
 
 
 
Mappings are established with:  
When tracklang-region-codes.tex is input, it can load additional files that provide supplementary mappings. 
 
 
Plain TeX:  
 
This command defines:  
See Table A.2 for a summary of all the mappings  that are provided by the file tracklang-scripts.tex. 
 
 
 
 
 
 
 
 
 
 
 
The tracklang package tries to track the loaded languages and the option names used to identify those languages. For want of a better term, the language option names are referred to as dialects even if they’re only a synonym for the language rather than an actual dialect. For example, if the user has requested british, the root language label is english and the dialect is british, whereas if the user requested UKenglish, the root language label is english and the dialect is UKenglish. The exceptions to this are the tracklang package options that have been specified in the form - (listed in Table 1.2). For example, the package option en-GB behaves as though the user requested the package option british. 
If  
 
In addition to the root language label and the dialect identifier, many of the language options also have corresponding ISO codes. In most cases there is an ISO 639-1 or an ISO 639-2 code (or both), and in some cases there is an ISO 3166-1 code identifying the dialect region. Where a language has different ISO 639-2 (T) and 639-2 (B) codes,  the “T” version is assumed. 
When the tracklang.sty LaTeX package is loaded, it first attempts to find the language options through the package options supplied to tracklang. This means that any languages that have been supplied in the document class options should get identified (provided that the document class has used the standard option declaration mechanism). If no languages have been supplied in this way, tracklang.sty then attempts to identify language settings in the following order: 
 
 
 
 
 
 
 
 
 
Each identified language and dialect is added to the tracked language and tracked dialect lists. Note that the tracked language and tracked dialect are labels rather than proper nouns. If a dialect label is identical to its root language label, the label will appear in both lists. 
You can check whether or not any languages have been detected using:  
If you want to find out if any of the tracked dialects matches a particular language tag, you can use:  
For example (Plain TeX):  
Here’s an example that doesn’t have an exact match, but does have a partial match:  
You can iterate through each tracked dialect using:  
You can iterate through each tracked language using:  
The above for-loops use the same internal mechanism as LaTeX’s  
The provided control sequence  is updated at the start of each iteration to the current element. The loop is terminated when this control sequence is set to  
You can test if a root language has been detected using:  
You can test if a particular dialect has been detected using:  
For example:  
“british’’ has been specified. 
“flemish’’ hasn’t been specified. 
“dutch’’ has been specified. 
“english’’ or an English variant has been specified.  
You can find the root language label for a given tracked dialect using:  
You can find the tracked dialects from a given root language using:  
You can test if a language or dialect has a corresponding ISO code using:  
Alternatively, you can test if a particular ISO code has been defined using:  
You can fetch the language (or dialect) label associated with a given ISO code using:  
You can fetch the ISO code for a given code type using:  
The above commands do nothing in the event of an unknown code or code type, so if you accidentally get the wrong code type, you won’t get an error. If you’re unsure of the code type, you can use the following commands:  
 
 
 
The  
As from v1.3, the language tag for a given dialect can be obtained using:  
As from v1.3, each tracked dialect may also have an associated  modifier, which can be fetched using:  
You can test if a dialect has an associated modifier using:  
For example:  
Dialects: american (ISO 3166-1: “US’’; root: english). british (ISO 3166-1: “GB’’; root: english). canadian (ISO 3166-1: “CA’’; root: english). canadien (ISO 3166-1: “CA’’; root: french). dutch (no specific region; root: dutch). francais (no specific region; root: french). 
Language for ISO 3166-1 “GB’’: british. 
Language for ISO 3166-1 “CA’’: canadian,canadien. 
Country ISO 3166-1 code for “canadian’’: CA.  
As from v1.3, each tracked dialect may also have an associated  variant, which can be fetched using:  
You can test if a dialect has an associated variant using:  
As from v1.3, each tracked dialect may also have an associated  script, which can be fetched using:  
You can test if a dialect has an associated script using:  
Note that the script should be a recognised four-letter ISO 15924 code, such as Latn or Cyrl. If a dialect doesn’t have an associated script then the default for the root language should be assumed. For example, Latn for English dialects or Cyrl for Russian dialects. The default script for known languages can be obtained using:  
There’s a convenient expandable command for testing the script:  
The supplementary package tracklang-scripts provides some additional commands relating to writing systems, including commands  in the form  
For example, the following defines a command to check if the given dialect should use a Latin script:  
 
As from v1.3, each tracked dialect may also have a sub-language identifier (for example, arevela), which can be fetched using:  
You can test if a dialect has an associated sub-tag using:  
As from v1.3, each tracked dialect may also have additional information, which can be fetched using:  
You can test if a dialect has additional information using:  
Most packages that implement multilingual support have a set of language definition files for each supported language or dialect. It may be that only the root language is needed, if there are no variations between that language’s dialect (for the purposes of that package), or it may be that separate definition files are required for each dialect. However it can be awkward trying to map the requested dialect or language label to the file name. Should, say, the file containing the French code be called -french- or  -frenchb- or  -francais-? Should, say, the file containing the British English code be called -british- or  -UKenglish-? If you want to modularise the language support for your package so that each language module has a different maintainer will the maintainers know what tag to use for their language? 
To help with this, tracklang provides:  
There’s a convenient shortcut command new to version 1.3:  
The optional argument  is the code that actually inputs the required file. This defaults to  
The  
 
 
 
 
 
 
 
 
 
 
 
 
The ordered set of possible values of  is determined from the given dialect.  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
For example (pre v1.3):  
If, for example,  
 
 
 
If, for example,  
 
 
 
 
 
If, for example,  
If the dialect label is identical to the root language label then it means that all associated information is the default for that language. For example, in the above case of french, the script is Latn and the region is unspecified. The root language label can therefore be used as the fallback in the event of no other match but for the specific case where the dialect is identical to the root language then all unnecessary file name checks can be skipped. 
If you’re only providing support for the root languages (pre v1.3):  
The following  
Within the resource file -.ldf,  you can identify the file using (new to version 1.3):  
If  
The resource file can load another resource file  -.ldf,  using (new to version 1.3):  
It may be that you want to load a file depending on the input encoding. The inputenc package defines  
If you require the resource file and want to perform  if it’s loaded at this point or  if it’s already been loaded then you can use:  
If you want to load a resource file if it exists (without an error if it doesn’t exist), then you can use  
 
The above restriction on the resource files loaded through  
The polyglossia package has language caption hooks in the form   
Instead, tracklang provides a command to perform this set of conditionals using generic code:  
Note that this command is enabled through  
Since captions is a commonly used hook type, there’s  a shortcut command provided:  
There may be some hooks, such as  
Note that no expansion is performed on  when appending or redefining a hook. 
 
The examples in this section illustrate the above commands. 
 
This example is for a trivial package called animals.sty that defines three textual commands:  
Here’s the code for animals.sty:  
The animals-english.ldf file valid for both the Plain TeX and LaTeX formats contains:  
This means that if babel or polyglossia are loaded, the redefinitions are automatically performed whenever the language is changed, but if there’s no caption mechanism the user can switch the fixed names using the  
Here’s an example LaTeX document that doesn’t have any caption hooks:  
There is some redundancy with the above resource files. Consider the babel example above. The american dialect is the first option, so in that case animals-en-US.ldf is loaded followed by animals-english.ldf. This means that the  
If this redundancy is an issue (for example, there are so many redefinitions needed that it significantly slows the document build process), then it can be addressed with the following modifications. The animals-en-GB.ldf file is now:  
Note that polyglossia has a  
 
Earlier, I mentioned the search order for  
 
 
 
The reason for including just the country code as the  in the  file search is to allow for region rather than language dependent settings. For example, suppose I want to write a package that needs to know whether to use imperial or metric measurements in the document, but I also want to provide multilingual support. The language alone won’t tell me whether to use imperial or metric (for example, the US uses imperial and the UK uses metric for most product attributes). I could provide ldf files for every language and region combination, but this would result in a lot redundancy. 
 
The example package (regions.sty) below illustrates this.  
 
 
 
 
 
 
 
 
Here’s an example document that uses this package:  
This works because the  search looks for the country code before the root language label. However, this will fail if  the dialect label is the same as a root language label that has an associated territory, marked with † in Table 1.2, as then it will be picked up before the country code. 
In the above example,  regions-CA.ldf is matched rather than regions-french.ldf, so regions-CA.ldf is loaded by  
This assumes that there’s a country code ldf file available. This example needs a little modification to use default units in case the region is missing:  
Here’s another document that sets up dialects with tracklang labels that aren’t recognised by babel. This means that there’s no corresponding  
 
units: kg, mm, EUR.  
units: kg, mm, GBP.  
Note that these mappings aren’t needed if babel is loaded with the root language labels instead. For example:  
Some of the predefined tracklang dialects come with a mapping to the closest matching babel dialect label. For example, the option ngermanDE listed in Table 1.3 automatically provides a mapping to ngerman. Since a tracklang dialect label  can only map to one babel label, this can be problematic for synonymous labels such as british/UKenglish or american/USenglish. The default mappings used by tracklang are shown in Table 1.3. 
 
If you are writing a package that sets up the document languages (rather than a package that provides multilingual support if the user has already loaded a language package) then you can load tracklang and use the commands below to help other packages track your provided languages. (See also: Integrating tracklang.tex into Language Packages.) 
The tracklang package can be loaded using  
When using LaTeX, there’s a difference between the two. The first case prevents tracklang from picking up the document class options but skips the check for known language packages. This check is redundant since your package is the language package, so you need to decide whether or not to allow the user to set up the localisation information through the document class options. 
There’s a hook that, if defined, is performed by tracklang.sty after the package options have been loaded but before known language packages are checked:  
If you prefer  
If you just use  
To integrate tracklang into your language package, you need  to consider the following steps: 
 
If yes, then skip this step. Otherwise create a file with the relevant  
 
If yes, then skip this step. 
If your package is setting up a language that tracklang doesn’t recognise then you will need to define the root language using  
This usually won’t be the case as tracklang should support all languages that have an official ISO 639-1 alpha-2 code. 
If you simply have a different label from tracklang identifying the root language, then you can just set up your label as a dialect using  
 
If yes, then skip this step. Otherwise create a file with the relevant  
 
If no, then skip this step. Otherwise you can use  
 
 
 
When the user requests a particular dialect through your language package, you can notify tracklang of this choice using  
If there’s no matching dialect predefined by tracklang, you can just use  
If you are providing a captions hook mechanism in the form  
 
When the document author switches to a different language or dialect, the current localisation information can be set with:  
This will make the following commands available which may be of use to other packages: 
 
 
 
 
 
 
 
 
 
 
 
 
The tracklang-scripts.tex file isn’t automatically loaded, but if it is then, as from v1.4, it contains a hook at the end of the file that can be used to load additional files that define supplementary scripts. This entails creating a file called, say, mypackage-scripts.tex that contains:  
The supplementary file should be identified with:  
Additional information can be found in §4. 
 
The tracklang-region-codes.tex file isn’t automatically loaded, but if it is then, as from v1.4, it contains a hook at the end of the file that can be used to load additional files that define supplementary regions. This entails creating a file called, say, mypackage-regions.tex that contains:  
The supplementary file should be identified with:  
Additional information can be found in §4. 
 
(New to version 1.3.) If the root language isn’t recognised by tracklang (not listed in Table 1.2), then it can be defined (but not tracked at this point) using:  
You can then track this language using:   
 
A dialect label may be predefined with associated information that allows that particular combination to be easily tracked with  
If the dialect label doesn’t match the root language label then use:  
For compatibility with pre version 1.3,  if the dialect isn’t predefined by tracklang, then you can use:  
(New to version 1.3.) Many of the tracklang dialect labels don’t have a corresponding match in various language packages. For  example, tracklang provides ngermanDE but the closest match in babel is ngerman. This means that the caption hook  
(New to version 1.3.) If the root language label is recognised by tracklang, you can add the ISO codes using:  
As from v1.3, you can also provide a modifier for a given dialect using:  
Note that no sanitization is performed on  when the modifier is set explicitly through  
The modifier is typically obtained by parsing locale information in POSIX format.  
The information provided in the commands below (such as the script) are typically obtained by parsing the language tag. For example, with Serbian in the Latin alphabet the modifier would be latin whereas the script would be Latn:  
As from v1.3, you can provide a script (for example, Latn or Cyrl) using:  
As from v1.3, you can provide a variant for a given dialect using:  
As from v1.3, you can also provide a sub-language using:  
As from v1.3, you can also provide additional information using:  
 
Suppose I want to create a language package alien.sty that defines the martian language with regional dialects lowermartian and uppermartian. First, let’s suppose that tracklang recognises the root language martian:  
The resource files may need to set the mapping between the tracklang dialect label and the alien dialect label. For example, in alien-xx-YY.ldf:  
Now let’s consider the case where tracklang doesn’t know about the martian language. In this case the user can’t  track the dialect until the root language has been defined, so the user can’t use  
With tracklang v1.3. The new root language can be defined with a minor adjustment to the above code:  
Now other package writers who want to provide support for the Martian dialects can easily detect which language options the user requested through my package, without needing to know anything about my alien package. 
 
 
 
Region mappings are listed in Table A.1, and script mappings are listed in Table A.2. 
 
 
 
Provided by tracklang.sty to declare  as a package option that tracks . Provided by tracklang.tex, if not already defined, to ignore its argument. §3; 19 
 
 
If defined before tracklang.sty v1.3.8+ is loaded, this command will be done after package options have been processed but before the check for language packages, such as babel and polyglossia. §6; 72 
 
Adds the ISO 3166-1 code. 
 
Tracks a dialect. This command defines  
 
Adds a mapping between the given ISO code and language name. 
 
Shortcut for  
 
Adds the ISO 639-1, 639-2 and 639-3 codes, which must have previously been declared using  
 
Expands to  if there are any tracked languages, otherwise expands to . §5; 35 
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Defined by  
 
Expands to the current tracked tag. §5; 45 
 
Iterates through the list of tracked dialects. On each iteration  is set to the dialect tag and  is performed. §5; 37 
 
Iterates through the list of tracked languages. On each iteration  is set to the language tag and  is performed. §5; 37 
 
Expands to the extra information for . §5; 44 
 
Finds the tracked dialect that matches the given language tag and stores the dialect label in . If no match found,  will be empty. §5; 36 
 
Expands to the modifier for the given dialect. §5; 40 
 
Expands to the script for . §5; 42 
 
Expands to the sub-language for . §5; 44 
 
Expands to the modifier for . §5; 42 
 
Gets the language tag for . §5; 40 
 
Expands to  if there’s extra information for , otherwise expands to . §5; 44 
 
Expands to  if there’s a modifier for the given dialect, otherwise expands to . §5; 41 
 
Expands to  if there’s a script for , otherwise expands to . §5; 42 
 
Expands to  if there’s a sub-language for , otherwise expands to . §5; 44 
 
Expands to  if there’s a modifier for , otherwise expands to . §5; 42 
 
Does  if the dialect identified by  has been tracked, otherwise does . §5; 38 
 
If the given tracked dialect has an associated script and that script code matches the replacement text for the control sequence  then do  otherwise to . If the tracked dialect doesn’t have an associated script then the default script for the root language is tested. §5; 43 
 
Does  if the given ISO code has been defined otherwise does . §5; 39 
 
Does  if the language identified by  has been tracked, otherwise does . §5; 38 
 
Does  
 
Does  if the given language or dialect has a corresponding ISO code of the given type, otherwise does . §5; 39 
 
Conditional that indicates whether or not to show information messages. 
 
Conditional that indicates whether or not to show verbose messages. 
 
Conditional that indicates whether or not to show warnings. 
 
Sets the current tracked dialect. §6.2; 74 
 
Sets the extra information for  to . §6.6; 80 
 
Defines a mapping between a tracklang dialect label and the corresponding dialect label used by a language hook, such as  
 
Sets the modifier for the given  to . §6.6; 78 
 
Sets the script for  to . §6.6; 79 
 
Sets the sub-language for  to . §6.6; 80 
 
Sets the modifier for  to . §6.6; 79 
 
Expands to 639-3 (should not be redefined). §5; 40 
 
Expands to 639-2 (should not be redefined). §5; 40 
 
Defined by  
 
Expands to a comma-separated list of the tracked dialects with the given language. §5; 39 
 
Expands to the code associated with the given language or dialect identified by . §5; 39 
 
Expands to the language from the given dialect. §5; 39 
 
Expands to a comma-separated list of language or dialect labels associated with the given code. §5; 39 
 
As  
 
Adds  to the list of extra region code files that should be input by tracklang-region-codes.tex. §4; 31 
 
Adds  to the list of files that should be input by tracklang-scripts.tex. §4; 33 
 
A shortcut that just does  
 
For use within resource files, this can be used to add  to the appropriate hook. §5; 55 
 
Expands to the numeric code corresponding to the given alpha-3 code. §4; 30 
 
Expands to the numeric code corresponding to the given alpha-2 code. §4; 30 
 
Defines a predefined dialect label that can be used by  
 
Defines a new root language that’s declared as an option. 
 
Expands to  
 
May be defined using the same format as  
 
Set by  
 
Set by  
 
Set by  
 
Set by  
 
Queries environment variable if  
 
Expands to the default script for the given language. §5; 43 
 
Expands to the ISO 3166-1 country code for the given language. 
 
Expands to the ISO 639-2 language code associated with . 
 
Expands to the ISO 639-2 (B) language code associated with . 
 
Expands to the ISO 639-1 language code associated with . 
 
Expands to the root language label from the given ISO code (639-1 or 639-2 or 639-3). 
 
Does  if the argument is a single alphanumeric character otherwise does . 
 
Does  if the given language has a default script (but is not necessarily tracked), otherwise does . 
 
Does  if the given language has an ISO 3166-1 country code (but is not necessarily tracked), otherwise does . 
 
Expands to  if there’s a known mapping for the given , otherwise expands to . §4; 31 
 
Expands to  if there’s a known mapping for the given alpha-2 region code, otherwise expands to . §4; 30 
 
Does  if  has an ISO 639-2 code (but is not necessarily tracked), otherwise does . 
 
Does  if  has an ISO 639-2 (B) code (but is not necessarily tracked), otherwise does . 
 
Does  if  has an ISO 639-1 code (but is not necessarily tracked), otherwise does . 
 
Does  if  is known (but not necessarily tracked), otherwise does . 
 
Does  if the given language code (639-1 or 639-2 or 639-3) is recognised (but not necessarily tracked), otherwise does . 
 
Expands to  if there’s a known mapping for the given numeric region code, otherwise expands to . §4; 30 
 
Does  if the argument is a language tag otherwise does . 
 
Does  if the argument is a region tag otherwise does . 
 
Does  if the argument is a script tag otherwise does . 
 
Does  if the argument is a variant tag otherwise does . 
 
Expands to the label of the last tracked dialect. §6.5; 77 
 
Identifies a new language that may be tracked. Apart from , the other arguments may be empty if the information is unavailable. §6.5; 76 
 
Expands to the alpha-3 code corresponding to the given numeric code. §4; 31 
 
Expands to the alpha-2 code corresponding to the given numeric code. §4; 30 
 
Attempts to obtain locale information from the expansion of  
 
Defines a predefined dialect label that can be used by  
 
Sets up a language label for use with  
 
Analogous to  
 
Attempts to obtain locale information from the  
 
Attempts to obtain locale information from the  
 
Similar to  
 
Establishes a mapping between a numeric region code and alpha-2 and alpha-3 codes. §4; 31 
 
As  
 
Loads the dialect for the given package. §5; 45 
 
Defined by  
 
Loads the appropriate ldf file if it hasn’t already been loaded. §5; 53 
 
As  
 
Expands to the direction associated with the given alpha script code. §4; 33 
 
Expands to the name associated with the given alpha script code. §4; 32 
 
Expands to the numeric script code corresponding to the given alpha code. §4; 32 
 
Set by  
 
Expands to the parent of the given alpha script code. §4; 33 
 
Expands to  if the given alpha script code has a parent otherwise expands to . §4; 33 
 
Expands to  if there’s a known mapping for the given alpha script code otherwise expands to . §4; 32 
 
Expands to  if there’s a known mapping for the given numeric script code otherwise expands to . §4; 32 
 
Defines a mapping between an alpha code and a numeric code. §4; 32 
 
Expands to the alpha script code corresponding to the given numeric code. §4; 32 
 
Sets the parent for the given alpha script code. §4; 33 
 
Sets  
 
Sets  
 
Parse , which should be a regular, well-formed RFC 5646 language tag (not an irregular grandfather tag) and track the dialect. §3; 21 
 
Tracks the dialect identified by the given , which may either be a predefined language/dialect or in the same format as  
 
Tracks a predefined language or dialect. §3; 19 
 
Expands to 3166-1 (should not be redefined). §5; 40 
 
Expands to 639-1 (should not be redefined). §5; 40 
 
 
List of Tables
1. Introduction
\xpg@bcp@loaded) or  when the language options are specified in the document class option list. It works fairly well with translator but will additionally assume the root language was also requested when a dialect is specified. So, for example, 
 is equivalent to \usepackage[british]{translator}
\usepackage{tracklang}
 This means that \usepackage[british]{translator}
\usepackage[english,british]{tracklang}
\ForEachTrackedDialect will iterate through the list “english,british” instead of just “british”, which can result in some redundancy.\babelprovide command. As far as I can tell, the only stored list is in \bbl@loaded which only contains the languages loaded through package options.
 Similarly, if the german package has been loaded,  tracklang effectively does \TrackPredefinedDialect{ngerman}
\TrackPredefinedDialect{german}
 then the dialect list will just consist of “british” rather than “english,british”. This does, however, mean that if the user mixes class and package options, only the class options will be detected. For example: \documentclass[british]{article}
\usepackage{translator}
\usepackage{tracklang}
 In this case, only the british option will be detected. The user can therefore use the document class option (or tracklang package option) to override the dialect and set the country code (where provided). For example: \documentclass[british]{article}
\usepackage[french]{babel}
\usepackage{tracklang}
 This sets the dialect to mexicanspanish and the root language to spanish. \documentclass[es-MX]{article}
\usepackage[spanish]{babel}
\usepackage{tracklang}
\TrackPredefinedDialect, as illustrated above. 
\TrackPredefinedDialect)
 
ISO Tag 
Dialect Label 
ISO Tag 
Dialect Label 
 
cy-GB 
GBwelsh
 de-AT 
austrian 
 
de-AT-1996 
naustrian
 de-BE 
belgiangerman 
 
de-CH 
swissgerman
 de-CH-1996 
nswissgerman 
 
de-DE 
germanDE
 de-DE-1996 
ngermanDE 
 
en-AU 
australian
 en-CA 
canadian 
 
en-GB 
british
 en-GG 
guernseyenglish 
 
en-IE 
IEenglish
 en-IM 
isleofmanenglish 
 
en-JE 
jerseyenglish
 en-MT 
maltaenglish 
 
en-NZ 
newzealand
 en-US 
american 
 
es-AR 
argentinespanish
 es-BO 
bolivianspanish 
 
es-CL 
chilianspanish
 es-CO 
columbianspanish 
 
es-CR 
costaricanspanish
 es-CU 
cubanspanish 
 
es-DO 
dominicanspanish
 es-EC 
ecudorianspanish 
 
es-ES 
spainspanish
 es-GT 
guatemalanspanish 
 
es-HN 
honduranspanish
 es-MX 
mexicanspanish 
 
es-NI 
nicaraguanspanish
 es-PA 
panamaspanish 
 
es-PE 
peruvianspanish
 es-PR 
puertoricospanish 
 
es-PY 
paraguayspanish
 es-SV 
elsalvadorspanish 
 
es-UY 
uruguayspanish
 es-VE 
venezuelanspanish 
 
fr-BE 
belgique
 fr-CA 
canadien 
 
fr-CH 
swissfrench
 fr-FR 
france 
 
fr-GG 
guernseyfrench
 fr-JE 
jerseyfrench 
 
ga-GB 
GBirish
 ga-IE 
IEirish 
 
gd-GB 
GBscottish
 hr-HR 
croatia 
 
hu-HU 
hungarian
 id-IN 
bahasa 
 
it-CH 
swissitalian
 it-HR 
istriacountyitalian 
 
it-IT 
italy
 it-SI 
sloveneistriaitalian 
 
it-SM 
sanmarino
 it-VA 
vatican 
 
ms-MY 
malay
 mt-MT 
maltamaltese 
 
nl-BE 
flemish
 nl-NL 
netherlands 
 
pt-BR 
brazilian
 pt-PT 
portugal 
 rm-CH 
swissromansh
 sl-SI 
slovenia Other combinations need to be set with  \TrackLocale or \TrackLanguageTag
\GetTrackedLanguageTag{}
 
abkhaz (ab)
 afar (aa)
 afrikaans (af) 
 
akan (ak)
 albanian (sq)
 amharic† (am-ET) 
 
anglosaxon (ang)
 apache (apa)
 arabic (ar) 
 
aragonese† (an-ES)
 armenian (hy)
 assamese (as) 
 
asturian (ast)
 avaric (av)
 avestan (ae) 
 
aymara (ay)
 azerbaijani (az)
 bahasai† (id-IN) 
 
bahasam† (ms-MY)
 bambara† (bm-ML)
 bashkir (ba) 
 
basque (eu)
 belarusian (be)
 bengali (bn) 
 
berber (ber)
 bihari (bh)
 bislama† (bi-VU) 
 
bokmal† (nb-NO)
 bosnian (bs)
 breton† (br-FR) 
 
bulgarian (bg)
 burmese (my)
 catalan (ca) 
 
chamorro (ch)
 chechen (ce)
 chichewa (ny) 
 
chinese (zh)
 churchslavonic (cu)
 chuvash† (cv-RU) 
 
coptic (cop)
 cornish† (kw-GB)
 corsican (co) 
 
cree (cr)
 croatian (hr)
 czech (cs) 
 
danish (da)
 divehi† (dv-MV)
 dutch (nl) 
 
dzongkha† (dz-BT)
 easternpunjabi† (pa-IN)
 english (en) 
 
esperanto (eo)
 estonian (et)
 ewe (ee) 
 
faroese (fo)
 farsi (fa)
 fijian† (fj-FJ) 
 
finnish (fi)
 french (fr)
 friulan† (fur-IT) 
 
fula (ff)
 galician (gl)
 ganda† (lg-UG) 
 
georgian (ka)
 german (de)
 greek (el) 
 
guarani (gn)
 gujarati (gu)
 haitian† (ht-HT) 
 
hausa (ha)
 hebrew (he)
 herero (hz) 
 
hindi (hi)
 hirimotu† (ho-PG)
 icelandic† (is-IS) 
 
ido (io)
 igbo (ig)
 interlingua (ia) 
 
interlingue (ie)
 inuktitut (iu)
 inupiaq (ik) 
 
irish (ga)
 italian (it)
 japanese (ja) 
 
javanese (jv)
 kalaallisut (kl)
 kannada† (kn-IN) 
 
kanuri (kr)
 kashmiri† (ks-IN)
 kazakh (kk) 
 
khmer (km)
 kikuyu (ki)
 kinyarwanda (rw) 
 
kirundi (rn)
 komi† (kv-RU)
 kongo (kg) 
 
korean (ko)
 kurdish (ku)
 kwanyama (kj) 
 
kyrgyz (ky)
 lao (lo)
 latin (la) 
 
latvian (lv)
 limburgish (li)
 lingala (ln) 
 
lithuanian (lt)
 lsorbian† (dsb-DE)
 lubakatanga† (lu-CD) 
 
luxembourgish (lb)
 macedonian (mk)
 magyar (hu) 
 
malagasy (mg)
 malayalam† (ml-IN)
 maltese (mt) 
 
manx† (gv-IM)
 maori† (mi-NZ)
 marathi† (mr-IN) 
 
marshallese† (mh-MH)
 mongolian (mn)
 nauruan† (na-NR) 
 
navajo† (nv-US)
 ndonga (ng)
 nepali (ne) 
 
nko (nqo)
 norsk (no)
 northernndebele (nd) 
 
northernsotho (nso)
 nuosu† (ii-CN)
 nynorsk† (nn-NO) 
 
occitan (oc)
 ojibwe (oj)
 oriya (or) 
 
oromo (om)
 ossetian (os)
 pali (pi) 
 
pashto (ps)
 piedmontese† (pms-IT)
 polish (pl) 
 
portuges (pt)
 quechua (qu)
 romanian (ro) 
 
romansh† (rm-CH)
 russian (ru)
 samin (se) 
 
samoan (sm)
 sango (sg)
 sanskrit (sa) 
 
sardinian† (sc-IT)
 scottish (gd)
 serbian (sr) 
 
shona (sn)
 sindhi (sd)
 sinhalese† (si-LK) 
 
slovak (sk)
 slovene (sl)
 somali (so) 
 
southernndebele† (nr-ZA)
 southernsotho (st)
 spanish (es) 
 
sudanese (su)
 swahili (sw)
 swati (ss) 
 
swedish (sv)
 syriac (syr)
 tagalog† (tl-PH) 
 
tahitian† (ty-PF)
 tai (tai)
 tajik (tg) 
 
tamil (ta)
 tatar (tt)
 telugu† (te-IN) 
 
thai† (th-TH)
 tibetan (bo)
 tigrinya (ti) 
 
tonga† (to-TO)
 tsonga (ts)
 tswana (tn) 
 
turkish (tr)
 turkmen (tk)
 twi† (tw-GH) 
 
ukrainian† (uk-UA)
 undetermined (und)
 urdu (ur) 
 
usorbian† (hsb-DE)
 uyghur† (ug-CN)
 uzbek (uz) 
 
venda† (ve-ZA)
 vietnamese (vi)
 volapuk (vo) 
 
walloon (wa)
 welsh (cy)
 westernfrisian† (fy-NL) 
 
wolof (wo)
 xhosa (xh)
 yiddish (yi) 
 yoruba (yo)
 zhuang† (za-CN)
 zulu (zu) 
\GetTrackedLanguageTag{}\captions or \date, this is also included after the tag following a slash.
 
acadian (fr)
 american† (en-US)
 argentinespanish† (es-AR) 
 
australian† (en-AU)
 austrian† (de-AT)
 bahasa† (id-IN) 
 
belgiangerman† (de-BE)
 belgique† (fr-BE)
 bolivianspanish† (es-BO) 
 
brazil† (pt-BR)
 brazilian† (pt-BR)
 british† (en-GB) 
 
canadian† (en-CA)
 canadien† (fr-CA)
 chilianspanish† (es-CL) 
 
columbianspanish† (es-CO)
 costaricanspanish† (es-CR)
 croatia† (hr-HR) 
 
cubanspanish† (es-CU)
 cymraeg (cy)
 deutsch (de) 
 
dominicanspanish† (es-DO)
 ecudorianspanish† (es-EC)
 elsalvadorspanish† (es-SV) 
 
flemish† (nl-BE)
 francais (fr)
 france† (fr-FR) 
 
frenchb (fr)
 friulano† (fur-IT)
 friulian† (fur-IT) 
 
furlan† (fur-IT)
 gaeilge (ga)
 gaelic (gd) 
 
galicien (gl)
 GBirish† (ga-GB)
 GBscottish† (gd-GB) 
 
GBwelsh† (cy-GB)
 germanb (de)
 germanDE† (de-DE) 
 
guatemalanspanish† (es-GT)
 guernseyenglish† (en-GG / british)
 guernseyfrench† (fr-GG) 
 
honduranspanish† (es-HN)
 hungarian† (hu-HU)
 IEenglish† (en-IE / british) 
 
IEirish† (ga-IE)
 indon† (id-IN)
 indonesian† (id-IN) 
 
isleofmanenglish† (en-IM / british)
 istriacountycroatian† (hr-HR)
 istriacountyitalian† (it-HR) 
 
italy† (it-IT)
 jerseyenglish† (en-JE / british)
 jerseyfrench† (fr-JE) 
 
kurmanji (ku)
 latein (la)
 lowersorbian† (dsb-DE) 
 
malay† (ms-MY)
 maltaenglish† (en-MT / british)
 maltamaltese† (mt-MT) 
 
mexicanspanish† (es-MX)
 meyalu† (ms-MY)
 naustrian† (de-AT-1996) 
 
nbelgiangerman† (de-BE-1996 / ngerman)
 netherlands† (nl-NL)
 newzealand† (en-NZ) 
 
ngerman (de-1996)
 ngermanb (de-1996 / ngerman)
 ngermanDE† (de-DE-1996 / ngerman) 
 
nicaraguanspanish† (es-NI)
 nil (und)
 norwegian† (no-NO) 
 
nswissgerman† (de-CH-1996 / ngerman)
 panamaspanish† (es-PA)
 paraguayspanish† (es-PY) 
 
persian (fa)
 peruvianspanish† (es-PE)
 piemonteis† (pms-IT) 
 
polutoniko (el)
 polutonikogreek (el)
 portugal† (pt-PT) 
 
portuguese (pt)
 puertoricospanish† (es-PR)
 romanche (rm-CH) 
 
romansch (rm-CH)
 rumantsch (rm-CH)
 russianb (ru) 
 
sanmarino† (it-SM)
 serbianc (sr-Cyrl)
 serbianl (sr-Latn) 
 
sloveneistriaitalian† (it-SI)
 sloveneistriaslovenian† (sl-SI / slovenian)
 slovenia† (sl-SI / slovenian) 
 
slovenian (sl)
 spainspanish† (es-ES)
 swissfrench† (fr-CH) 
 
swissgerman† (de-CH)
 swissitalian† (it-CH)
 swissromansh† (rm-CH) 
 
UKenglish† (en-GB)
 ukraine† (uk-UA)
 ukraineb† (uk-UA) 
 
uppersorbian† (hsb-DE)
 uruguayspanish† (es-UY)
 USenglish† (en-US) 
 
valencian (ca)
 valencien (ca)
 vatican† (it-VA) 
 venezuelanspanish† (es-VE) 2. Summary of Use
 
\descriptionname or datetime2 to provide localised  formats or time zone information);2.1. Document Level
2.1.1. Generic TeX
\input. See §2.1.2 for LaTeX use.\input tracklang.tex % v1.3
\TrackLangFromEnv
% load packages that use tracklang for localisation
 Or (texosquery v1.2) \input texosquery.tex
\input tracklang.tex % v1.3
\TrackLangFromEnv
% load packages that use tracklang for localisation
 A Unix-like user who may or may not have texosquery setup to run in the shell escape: \input texosquery.tex % v1.2
\input tracklang.tex % v1.3
\TeXOSQueryLangTag{\langtag}
\TrackLanguageTag{\langtag}
% load packages that use tracklang for localisation
\input texosquery.tex
\input tracklang.tex % v1.3
\ifx\TeXOSQueryLangTag\undefined
 \TrackLangFromEnv
\else
 \TeXOSQueryLangTag{\langtag}
 \TrackLanguageTag{\langtag}
\fi
% load packages that use tracklang for localisation
\input tracklang.tex % v1.3
\TrackLanguageTag{hy-Latn-IT-arevela}
% load packages that use tracklang for localisation
\input tracklang.tex
\TrackPredefinedDialect{british}
% load packages that use tracklang for localisation
\languagename): 
 Additional information about the script can be obtained by also loading tracklang-scripts: \SetCurrentTrackedDialect{\languagename}
Dialect: \CurrentTrackedDialect.
Language: \CurrentTrackedLanguage.
ISO Code: \CurrentTrackedIsoCode.
Region: \CurrentTrackedRegion.
Modifier: \CurrentTrackedDialectModifier.
Variant: \CurrentTrackedDialectVariant.
Script: \CurrentTrackedDialectScript.
Sub-Lang: \CurrentTrackedDialectSubLang.
Additional: \CurrentTrackedDialectAdditional.
Language Tag: \CurrentTrackedLanguageTag.
 The name, numeric code and direction can now be obtained: \input tracklang-scripts.tex
Name: 
 Test for a specific script (in this case Latn): \TrackLangScriptAlphaToName{\CurrentTrackedDialectScript}.
Numeric: 
\TrackLangScriptAlphaToNumeric{\CurrentTrackedDialectScript}.
Direction: 
\TrackLangScriptAlphaToDir{\CurrentTrackedDialectScript}.
Latin?
\ifx\CurrentTrackedDialectScript\TrackLangScriptLatn
 Yes
\else
 No
\fi
2.1.2. LaTeX
\xpg@bcp@loaded is defined, you just need to make sure the languages are set before tracklang is loaded: 
 For older versions of polyglossia where the regional information is required, use recognised class options: \documentclass{article}
\usepackage{polyglossia}
\setmainlanguage[variant=uk]{english}
% load packages that use tracklang for localisation
\documentclass[en-GB]{article}
\usepackage{polyglossia}
\setmainlanguage[variant=uk]{english}
% load packages that use tracklang for localisation
 If the region is important but there’s no babel dialect that represents it, there are several options. The first method is to use the class options recognised by tracklang and the root language labels when loading babel: \documentclass[british,canadien]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
% load packages that use tracklang for localisation
\documentclass[en-IE,ga-IE]{article}
\usepackage[english,irish]{babel}
% load packages that use tracklang for localisation
\TrackLanguageTag and map the new dialect label to the nearest matching \captions: 
 This ensures that the \documentclass{article}
\usepackage{tracklang}% v1.3
\TrackLanguageTag{en-MT}
\SetTrackedDialectLabelMap{\TrackLangLastTrackedDialect}{UKenglish}
\usepackage[UKenglish]{babel}
% load packages that use tracklang for localisation
\captionsUKenglish hook is detected by the localisation packages. This mapping isn’t needed for polyglossia as the caption hooks use the root language label. This mapping also isn’t needed if british is used instead of UKenglish since the en-MT (maltaenglish) predefined dialect automatically sets up a mapping to british. (The default mappings are shown in Table 1.3.)\babelprovide. If you are using \babelprovide, you will need to use the class option or \TrackLanguageTag as above.2.2. Locale-Sensitive Packages
 (Most of the commands used in this section require at least tracklang version 1.3 but 1.4 is better if you want to include the script tag in the ldf files.) Note that tracklang.tex has a check to determine if it’s already been loaded, so you don’t need to worry about that.\input tracklang.tex
 This will picked up any language options supplied in the document class options and will also detect if babel or polyglossia have been loaded.\RequirePackage{tracklang}[2019/11/30]% at least v1.4
 This means the user can do, say, \DeclareOption*{\TrackLanguageTag{\CurrentOption}}
 With at least version 1.4, it’s better to use \usepackage[hy-Latn-IT-arevela]{mypackage}
\TrackIfKnownLanguage: \DeclareOption*{% 
 \TrackIfKnownLanguage{\CurrentOption}% 
 {% successful
  \PackageInfo{mypackage}{Tracking language `\CurrentOption'}% 
 }% 
 {% failed
  \PackageError{mypackage}% 
  {Unknown language specification `\CurrentOption'}% 
  {You need to supply either a known dialect label 
   or a valid language tag}% 
 }% 
}
\def and \ifx with more appropriate LaTeX commands. \AnyTrackedLanguages
{}
{% fetch locale information from the operating system
  \ifx\TeXOSQueryLangTag\undefined
    % texosquery v1.2 not available
    \TrackLangFromEnv
  \else
    % texosquery v1.2 available
    \TeXOSQueryLangTag{\langtag}
    \TrackLanguageTag{\langtag}
  \fi
}
\def\fooname{Foo}
\def\barname{Bar}
\AnyTrackedLanguages
{% 
  \ForEachTrackedDialect{\thisdialect}{% 
    \TrackLangRequireDialect{mypackage}{\thisdialect}% 
  }% 
}
{}% no tracked languages, default already set up
\IfTrackedLanguageFileExists below for further details.)% identify this file:
 This sets up appropriate the \TrackLangProvidesResource{english}[2016/10/06 v1.0]
\TrackLangAddToCaptions{% 
  \def\fooname{Foo}% 
  \def\barname{Bar}% 
}
\captions hook (if it’s found). For other hooks, such as \date, use  \TrackLangAddToHook or \TrackLangRedefHook instead.\CurrentTrackedDialectScript). Here’s an example for a language with different writing systems. The resource file for Serbian mypackage-serbian.ldf: % identify file:
 The file mypackage-serbian-Latn.ldf sets up the Latin script (Latn): \TrackLangProvidesResource{serbian}[2016/10/06 v1.0]
\TrackLangRequestResource{serbian-\CurrentTrackedDialectScript}
{}% file not found, do something sensible here
 The file mypackage-serbian-Cyrl.ldf sets up the Cyrillic script (Cyrl): \TrackLangProvidesResource{serbian-Latn}[2016/10/06 v1.0]
\TrackLangAddToCaptions{% 
  \def\fooname{...}% provide appropriate Latin translations
  \def\barname{...}% 
}
 With v1.4+ you just need mypackage-sr-Latn.ldf and mypackage-sr-Cyrl.ldf for the regionless versions.\TrackLangProvidesResource{serbian-Cyrl}[2016/10/06 v1.0]
\TrackLangAddToCaptions{% 
  \def\fooname{...}% provide appropriate Cyrillic translations
  \def\barname{...}% 
}
2.3. Language Packages
 Alternative LaTeX use: \input tracklang
 Unlike \RequirePackage{tracklang}[2019/11/30]% v1.4
\input, \RequirePackage will allow tracklang to pick up the document class options, but using \RequirePackage will also trigger the tests for known language packages. (If you want to find out if tracklang has already been loaded and locales have already been tracked, you can use the same code as in the previous section.)\TrackPredefinedDialect or \TrackLanguageTag. For example, if the user requests british, that’s a predefined dialect so you can just do: 
 Alternatively \TrackPredefinedDialect{british}
 If your package uses caption hooks, then you can set up  a mapping between tracklang’s internal dialect label and your caption label. For example, let’s suppose the closest match to English used in Malta (en-MT) is the  dialect UKenglish (for example, the date format is  similar between GB and MT): \TrackLanguageTag{en-GB}
 (The predefined maltaenglish option provided by tracklang automatically sets the mapping to british, but the above method will change that mapping to UKenglish.)\TrackLanguageTag{en-MT}
\SetTrackedDialectLabelMap{\TrackLangLastTrackedDialect}{UKenglish}
\def\captionsUKenglish{% 
  \def\contentsname{Contents}% 
  % ...
}
\TrackLangAddToHook and \TrackLangRedefHook commands can find your language hooks. You don’t need the map if your dialect label is the same as tracklang’s root language label for that locale. For example: \TrackLanguageTag{en-MT}
\def\captionsenglish{% 
  \def\contentsname{Contents}% 
  % ...
}
\selectlanguage it would be useful to also use \SetCurrentTrackedDialect{}\SetTrackedDialectLabelMap. It may also be the root language label, in which case tracklang will search for the last dialect to be tracked with that language. For example: 
 See the example in §2.1 or the example in  Integrating tracklang.tex into Language Packages.\def\selectlanguage#1{% 
  \SetCurrentTrackedDialect{#1}% 
  % set up hyphenation patterns etc
}
3. Generic Use
 or for TeX formats that have an argument form for \input tracklang
\input: 
 As from version 1.3, you don’t need to change the category code of \input{tracklang}
@ before loading tracklang.tex as it will automatically be changed to 11 and switched back at the end (if required).
 If \DeclareOption{}{\TrackPredefinedDialect{}}
\@tracklang@declareoption isn’t defined when tracklang.tex is input, it will be defined to ignore its argument.\@tracklang@declareoption to use something analogous to \DeclareOption, if appropriate. Otherwise, the document languages need to be explicitly identified (using any of the following commands) so that tracklang knows about them.
 is the Plain TeX alternative to: \input tracklang
\TrackPredefinedDialect{british}
\documentclass[british]{article}
\usepackage{tracklang}
\TrackPredefinedDialect, otherwise  needs to be in one the following formats: 
 where  is the ISO 639-1 or 639-2 code identifying the language (lower case),  is the 3166-1 ISO code identifying the territory (upper case) and   is the modifier or variant. The hyphen (-) may be replaced by an underscore character  (_). Code-set information in the form .de (modifier is new) or -DE.utf8@newen (modifier is missing). The code-set will be ignored if present, but it won’t interfere with the parsing.-GB.utf8
 indicates German in Namibia using the new spelling.\TrackLocale{de-NA@new}
deu may be used instead of de, but ger won’t be recognised.) \TrackLanguageTag and \TrackIfKnownLanguage will check if  is a predefined option. (This saves parsing the tag if it’s recognised.)
 This will track hy-Latn-IT-arevela and brazilian (pt-BR) but not Latn-ME (because it doesn’t contain a valid language code) even though it’s a valid script and country code. The above is just for illustrative purposes. Typically the language tracking isn’t performed within the document text.\TrackLanguageTag{hy-Latn-IT-arevela}
Latn-ME: \TrackIfKnownLanguage{Latn-ME}{success}{fail}.
brazilian: \TrackIfKnownLanguage{brazilian}{success}{fail}.
 but users can make mistakes sometimes and this won’t provide any helpful information if they, for example, misspelt a package option or forgot the “=” part of a = setting. Instead (as from v1.5.5) datetime2 now does: \TrackLanguageTag{\CurrentOption}
 This will now give the user some guidance. \TrackIfKnownLanguage{\CurrentOption}
{...}% known language
{\PackageError{...}{...}{...}}
 creates a new dialect with the label \TrackLanguageTag{zh-cmn-Hans-CN}
zhcmnHansCN. The root language chinese has the 639-1 code zh and the dialect zhcmnHansCN has the ISO 639-3 code cmn. ISO 639-1: 
\TrackedIsoCodeFromLanguage{639-1}{chinese}.
ISO 639-3: \TrackedIsoCodeFromLanguage{639-3}{zhcmnHansCN}.
\TeXOSQueryLangTag, which may be used to fetch the operating system’s regional information as a language tag. These commands can be used as follows: 
 (If the shell escape is disabled, \input tracklang % v1.3
\input texosquery % v1.2
\TeXOSQueryLangTag{\langtag}
\TrackLanguageTag{\langtag}
\langtag will be empty, which will trigger a warning but no errors.)\TrackLocale is used with just the language ISO code, no region is tracked for that language. For example 
 will track the IM (Isle of Man) ISO 3166-1 code but \TrackLocale{manx}
 won’t track the region. Similarly for \TrackLocale{gv}
\TrackLanguageTag.\TrackLocale that doesn’t take an argument: \directlua is available, this will try to get the language information from the system environment variables LC_ALL or LANG and, if successful, track that.C or POSIX or starts with a forward slash / then the locale value is treated as empty.\TeXOSQueryLocale as a fallback if texosquery has been loaded. Since texosquery requires both the shell escape and the Java runtime environment, tracklang doesn’t automatically load it.
 Document build: \input texosquery
\input tracklang
\TrackLangFromEnv
etex --shell-escape 
 Document build: \usepackage{texosquery}
\usepackage{tracklang}
\TrackLangFromEnv
pdflatex --shell-escape 
LANG set to  en on my Linux system so instead of _GB.utf8
 I can use \TrackPredefinedDialect{british}
\TrackLangFromEnv
 However, this only helps subsequently loaded packages that use tracklang to determine the required regional  settings. For example: \documentclass{article}
\usepackage{tracklang}
\TrackLangFromEnv
 In my case, with the \documentclass{article}
\usepackage{tracklang}
\TrackLangFromEnv
\usepackage[useregional]{datetime2}
LANG environment variable set to en and the shell escape enabled, this automatically switches on the  en-GB date style. Naturally this doesn’t help locale-sensitive packages that don’t use tracklang._GB.utf8\TrackLangFromEnv command also incidentally sets \TrackLangEnv to the value of the environment variable or empty if the query was unsuccessful (for example, the shell escape is unavailable).\TrackLangFromEnv is used, then the environment variable won’t be queried and the value of \TrackLangEnv will be parsed instead._ with its usual category code 8, then tries splitting  on a hyphen - with category code 12, and then tries  splitting on the underscore _ with category code 12. 
 This doesn’t perform a shell escape since \def\TrackLangEnv{en-GB}
\TrackLangFromEnv
\TrackLangEnv is already defined. In this case, you may just as well use: 
 (unless you happen to additionally require the component commands that are set by \TrackLocale{en-GB}
\TrackLangFromEnv, see below.)tex "
\\def\\TrackLangEnv{$LANG}\\input myDoc"
\TrackLangFromEnv command also happens to store the component parts of the environment variable value in the following commands. (These aren’t provided by \TrackLocale.) If the information is unavailable, the relevant commands will be set to empty.\TrackLangEnv (empty if  unsuccessful). Unlike \TrackLangFromEnv, this doesn’t check if \TrackLangEnv already exists. A warning will occur if the shell escape is unavailable. For systems that store the locale information in environment variables, this is more efficient than using texosquery’s \TeXOSQueryLocale command (which is what’s used as the fallback).LC_ALL and, if that is unsuccessful, then queries LANG (before optionally falling back on  texosquery). If you want another environment variable tried after LC_ALL and before LANG, you can instead use: LC_MONETARY: \TrackLangQueryOtherEnv{LC_MONETARY}
\TrackLangEnv, you can use it before \TrackLangFromEnv. For example: 
 Remember that if you only want to do the shell escape if \TrackLangQueryOtherEnv{LC_MONETARY}
\TrackLangFromEnv
\TrackLangEnv hasn’t already been defined, you can test for this first: \ifx\TrackLangEnv\undefined
  \TrackLangQueryOtherEnv{LC_MONETARY}
\fi
\TrackLangFromEnv
\TrackLangEnv without tracking the result using: \TrackLangFromEnv but assumes that  \TrackLangEnv has already been set and doesn’t track the  result. The component parts are stored as for \TrackLangFromEnv.
 This produces: \input tracklang
\def\TrackLangEnv{fr-BE.utf8@euro}
\TrackLangParseFromEnv
Language: \TrackLangEnvLang.
Territory: \TrackLangEnvTerritory.
Codeset: \TrackLangEnvCodeSet.
Modifier: \TrackLangEnvModifier.
Any tracked languages? \AnyTrackedLanguages{Yes}{No}.
 This produces:\input tracklang
\def\TrackLangEnv{fr-BE.utf8@euro}
\TrackLangFromEnv
Language: \TrackLangEnvLang.
Territory: \TrackLangEnvTerritory.
Codeset: \TrackLangEnvCodeSet.
Modifier: \TrackLangEnvModifier.
Any tracked languages? \AnyTrackedLanguages{Yes}{No}.
Tracked dialect(s):% 
\ForEachTrackedDialect{\thisdialect}{\space\thisdialect}.
\TrackLangFromEnv doesn’t recognise the given language and territory combination, it will define a new dialect and add that.en-BE, so the sample document below defines a new dialect labelled enBEeuro: 
 This now produces: \input tracklang
\def\TrackLangEnv{en-BE.utf8@euro}
\TrackLangFromEnv
Language: \TrackLangEnvLang.
Territory: \TrackLangEnvTerritory.
Codeset: \TrackLangEnvCodeSet.
Modifier: \TrackLangEnvModifier.
Any tracked languages? \AnyTrackedLanguages{Yes}{No}.
Tracked dialect(s):% 
\ForEachTrackedDialect{\thisdialect}{\space\thisdialect}.
4. Supplementary Packages
\TrackLanguageTag encounters a numeric region code, it will automatically input tracklang-region-codes.tex, if it hasn’t already been input. This file provides the following commands.
 There’s a simple wrapper package tracklang-scripts.sty for LaTeX users: \input tracklang-scripts
\usepackage{tracklang-scripts}
\IfTrackedDialectIsScriptCs.\TrackLangScriptSetParent then it will be considered defined, but if the  argument was empty in  \TrackLangScriptMap, then it will be undefined.5. Detecting the User’s Requested Languages
\TrackLocale or \TrackLangFromEnv are used and the locale isn’t recognised a new dialect is created with the label formed from the ISO codes (and modifier, if present).  Similarly for \TrackLanguageTag a new dialect is created with a label that’s essentially the language tag without the hyphen separators. For example,  
 will add a new dialect with the label \TrackLocale{xx-YY}
xxYY, 
 will add a new dialect with the label \TrackLocale{xx-YY@mod}
xxYYmod and  
 will add a new dialect with the label \TrackLanguageTag{xx-Latn-YY}
xxLatnYY.\TrackLocale or \TrackLangFromEnv find a modifier, the  value will be sanitized to allow it to be used as a label. If the modifier is set explicitly using \SetTrackedDialectModifier,  no sanitization is performed. 
 
Note that this references internal commands provided by other packages. Of these, only the polyglossia commands are documented in the package manual, and so are the only ones that can be relied on.\bbl@loaded is defined (babel), tracklang will iterate over each label in that command definition;\trans@languages is defined (translator),  tracklang will iterate over each label in that command definition;
 
\xpg@bcp@loaded has been defined, tracklang will iterate over the BCP 47 tags in that command definition;\xpg@loaded has been defined, tracklang will iterate over each language label in that command definition;\GetTrackedDialectFromLanguageTag). This will be empty if no tracked dialects match on the root language or if there’s a tracked dialect label that exactly matches the label formed by concatenating the language code, sub-language, script, region, modifier and variant.
 This matches because the territory code 826 is recognised as equivalent to the code GB, and the default script for english is Latn. In this case, the dialect label is british. Note that this doesn’t require the use of \input tracklang
\TrackLanguageTag{en-826}
Has en-Latn-GB been tracked?
\GetTrackedDialectFromLanguageTag{en-Latn-GB}{\thisdialect}% 
\ifx\thisdialect\empty
 No!
\else
 Yes! Dialect label: \thisdialect.
\fi
\bye
\TrackLanguageTag to track the dialect.  It also works if the dialect has been tracked using other commands, such as \TrackLocale.
 In this case the result is: \input tracklang
\TrackLanguageTag{de-CH-1996}
Has de-DE-1996 been tracked?
\GetTrackedDialectFromLanguageTag{de-DE-1996}{\thisdialect}% 
\ifx\thisdialect\empty
 No!
  \ifx\TrackedDialectClosestSubMatch\empty
    No match on root language.
  \else
    Closest match: \TrackedDialectClosestSubMatch.
  \fi
\else
 Yes! Dialect label: \thisdialect.
\fi
\bye
\@for loop. Since this isn’t defined by TeX, a similar command (\@tracklang@for) will be defined that works in the same way.\@nil. This special control sequence should never been used as it’s just a marker and isn’t actually defined. If you get an error message stating that \@nil is undefined, then it’s most likely due to a loop control sequence being used outside the loop. This can occur if the loop contains code that isn’t expanded until later. For example, if the loop code includes \AtBeginDocument, you need to ensure that the loop control sequence is expanded before being added to the hook.
 This produces: \documentclass[british,dutch]{article}
\usepackage{tracklang}
\begin{document}
``english'' \IfTrackedDialect{english}{has}{hasn't} been specified.
``british'' \IfTrackedDialect{british}{has}{hasn't} been specified.
``flemish'' \IfTrackedDialect{flemish}{has}{hasn't} been specified.
``dutch'' \IfTrackedDialect{dutch}{has}{hasn't} been specified.
``english'' or an English variant 
\IfTrackedLanguage{english}{has}{hasn't} been specified.
\end{document}
\TrackLanguageTag.\TrackedLanguageFromIsoCode, this command only expands to a single label rather than a comma-separated list.\TrackLanguageTag.\Get… commands below are designed to be expandable. If the supplied  is unrecognised they expand to empty. Remember that the dialect must first be identified as a tracked  language for it to be recognised.\TrackLocale or \TrackLangFromEnv but may be set explicitly. (See §6 for setting this value. Likewise for the following commands.)
 This produces: \documentclass[british,francais,american,canadian,canadien,dutch]{article}
\usepackage{tracklang}
\begin{document}
Languages:
\ForEachTrackedLanguage{\ThisLanguage}{\ThisLanguage\space
(ISO \TwoLetterIsoLanguageCode: 
``\TrackedIsoCodeFromLanguage{\TwoLetterIsoLanguageCode}{\ThisLanguage}''). }
Dialects:
\ForEachTrackedDialect{\ThisDialect}{\ThisDialect\space 
(\IfTrackedLanguageHasIsoCode{\TwoLetterIsoCountryCode}{\ThisDialect}% 
 {ISO \TwoLetterIsoCountryCode: 
  ``\TrackedIsoCodeFromLanguage{\TwoLetterIsoCountryCode}{\ThisDialect}''} {no specific region};
root: \TrackedLanguageFromDialect{\ThisDialect}). }
Language for ISO \TwoLetterIsoCountryCode\ ``GB'':
\TrackedLanguageFromIsoCode{\TwoLetterIsoCountryCode}{GB}.
Language for ISO \TwoLetterIsoCountryCode\ ``CA'': 
\TrackedLanguageFromIsoCode{\TwoLetterIsoCountryCode}{CA}.
Country ISO \TwoLetterIsoCountryCode\ code for ``canadian'':
\TrackedIsoCodeFromLanguage{\TwoLetterIsoCountryCode}{canadian}.
\end{document}
\TrackLanguageTag but may be set explicitly.\TrackLangScript where  is the ISO 15924 four-letter code. If the dialect doesn’t have an associated script,  is done. This package isn’t loaded automatically, so you’ll need to explicitly load it. The generic code is in tracklang-scripts.tex: 
 There’s a convenient LaTeX wrapper tracklang-scripts.sty: \input tracklang-scripts
 See §4 for further details of that package.\usepackage{tracklang-scripts}
\input tracklang-scripts
\def\islatin#1#2#3{% 
  \IfTrackedDialectIsScriptCs{#1}{\TrackLangScriptLatn}{#2}{#3}% 
}
\CurrentTrackedTag is set to the final attempt at determining .\IfTrackedLanguageFileExists to input the resource file if found. The prefix is given by - and the suffix is .ldf. A warning is issued if no resource file is found. Note that while it makes sense for  to be the same as the base name of the package that uses these resource files, they don’t have to be the same. This command additionally defines: 
 to , which allows the prefix to be picked up by resource file commands, such as \TrackLangProvidesResource and \TrackLangRequireResource. (See below.)\TrackLangRequireResource{\CurrentTrackedTag}
\IfTrackedLanguageFileExists command sets up the current tracked dialect with: 
 which enables the following commands that may be used within   or : 
 Expands to the dialect label.\SetCurrentTrackedDialect{dialect}
\CurrentTrackedRegion will expand to that code, otherwise it will be empty.\CurrentTrackedTag.\IfTrackedLanguageFileExists behaves as follows: 
 
\CurrentTrackedTag is empty.
 
\CurrentTrackedTag is set to the current  in the set. The rest of the set of possible values of  is skipped.\CurrentTrackedTag is set to the final  in the set (the language label). 
\IfTrackedLanguageFileExists. Note that the set may contain repetitions (for example, if the dialect label is the same as the root language label). If an item contains an element that hasn’t been set (such as the ISO 639-3 code or a sub-language  or variant) then that item is skipped. 
 
\CurrentTrackedLanguageTag.---.--.-- (if there’s no script or if the script is the default for the given language). - (if there’s no script or if the script is the default for the given language).--.-.-.---.--.--region (if there’s no script or if the script is the default for the given language). - (if there’s no script or if the script is the default for the given language).--.-.-. ---.--.-- (if there’s no script or if the script is the default for the given language). - (if there’s no script or if the script is the default for the given language).--.-.-.-- or - if  is missing.-- or - if  is missing.-- or - if  is missing.\CurrentTrackedLanguage (the root language label). 
 With version 1.3 onwards, this can be written more concisely as: \AnyTrackedLanguages
{% 
  \ForEachTrackedDialect{\ThisDialect}% 
  {% try to load the language file for this dialect
    \IfTrackedLanguageFileExists{\ThisDialect}% 
    {mypackage-}% file prefix
    {.ldf}% file suffix
    {\input mypackage-\CurrentTrackedTag.ldf}% file found
    {% file not found
      \PackageWarning{mypackage}{No support for language
       `\ThisDialect'}% 
    }% 
  }% 
}
{% no languages detected so use defaults
}
 which additionally enables the tracklang version 1.3 commands described below, such as \AnyTrackedLanguages
{% 
  \ForEachTrackedDialect{\ThisDialect}% 
  {% try to load the language file for this dialect
    \TrackLangRequireDialect{mypackage}{\ThisDialect}% 
  }% 
}
{% no languages detected so use defaults
}
\TrackLangRequireResource.\ThisDialect is british, then the file search will be in the order: 
 
\ThisDialect is naustrian, then the file search will be in the order: 
 
\ThisDialect is francais, then the file search will be in the order:  
 
This is because the predefined francais option has no region assigned to it. Be careful if the dialect label is the actual root language. For example, if\ThisDialect is french, then the file search will be in the order: 
 
Note that the last try will always fail in this case since if the file exists, it will be found on the second try.
 With version 1.3 onwards, this can be written more concisely as: \AnyTrackedLanguages
{% 
  \ForEachTrackedLanguage{\ThisLanguage}% 
  {% try to load the language file for this root language
    \IfTrackedLanguageFileExists{\ThisLanguage}% 
    {mypackage-}% file prefix
    {.ldf}% file suffix
    {\input mypackage-\CurrentTrackedTag.ldf}% file found
    {% file not found
      \PackageWarning{mypackage}{No support for language
       `\ThisLanguage'}% 
    }% 
  }% 
}
{% no languages detected so use defaults
}
 which additionally enables the commands described below. Note that in this case, if more than one dialect for the same language has been tracked, only the hooks for the last dialect for that language will be adjusted, so it’s usually best to iterate over the dialects.\AnyTrackedLanguages
{% 
  \ForEachTrackedLanguage{\ThisLanguage}% 
  {% try to load the language file for this root language
    \TrackLangRequireDialect{mypackage}{\ThisLanguage}% 
  }% 
}
{% no languages detected so use defaults
}
\TrackLang…Resource… commands may  only be used in resource files that are loaded using \TrackLangRequireDialect. An error will occur if the file is input through some other method.\ProvidesFile is defined (through the LaTeX kernel) this is used, otherwise a simplified generic alternative is used that’s  suitable for other TeX formats.% (In file foo-en-GB.ldf)
% Declare this regional file:
 If foo-english.ldf is also identified with \TrackLangProvidesResource{en-GB}
% load root language file foo-english.ldf:
\TrackLangRequireResource{english}
\TrackLangProvidesResource, this will ensure that it’s only loaded once.\inputencodingname, but this is only used with pdfLaTeX. To avoid repeated tests to determine whether or not \inputencodingname has been defined, you can use: utf8 if \inputencodingname hasn’t been defined, otherwise it will expand to \inputencodingname. For example: \InputIfFileExists{foo-\TrackLangEncodingName.ldf}
{% support available for the document encoding
}
{% no support for the document encoding
}
\…Resource… commands are only permitted within the resource files. They are internally enabled through \TrackLangRequireDialect. \TrackLangRequireDialect, and the fact that it internally uses \IfTrackedLanguageFileExists, means that commands like \CurrentTrackedLanguage or \CurrentTrackedDialect may be used in those files. This means that the name of the captions hook can be obtained through them. (Remember that the file foo-en-GB.ldf might have been loaded with, say, the british dialect or with the synonymous UKenglish dialect or with a dialect label that doesn’t have a corresponding caption hook, such as enGBLatn.)\captions (where  is the root language label) whereas babel has dialect captions hooks in the form \captions (where  is the dialect label). This leads to a rather cumbersome set of conditionals: 
 Note that the above has been simplified through the use of etoolbox commands, which isn’t suitable for generic use. It also doesn’t query the mapping from tracklang’s dialect label to the closest matching babel dialect label.\ifcsundef{captions\CurrentTrackedLanguage}
{% 
  \ifcsundef{captions\CurrentTrackedDialect}% 
  {}% 
  {% 
    \csgappto{captions\CurrentTrackedDialect}{% 
      % code to append to hook
    }% 
  }% 
}% 
{% 
  \csgappto{captions\CurrentTrackedLanguage}{% 
    % code to append to hook
  }% 
}
% do code now to initialise
\captionsngerman when the package is loaded, not at the start of the document).\TrackLangRequireDialect so should only be used inside resource files.\TrackLangAddToHook{}{captions}
\date, that need redefining rather than appending to, so there’s an analogous command: 5.1. Examples
5.1.1. animals.sty
\catname, \dogname and \ladybirdname. The default values are: “cat”, “dog” and “bishy-barney-bee”.1 The supported languages are defined in files animals-.ldf.% Example package animals.sty
 Here’s a Plain TeX version that picks up the language from the locale environment variable: \NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{animals}
\RequirePackage{tracklang}[2019/11/30]% v1.4
% Any undeclared options are language settings:
\DeclareOption*{% 
 \TrackIfKnownLanguage{\CurrentOption}% 
 {% successful
  \PackageInfo{animals}{Tracking language `\CurrentOption'}% 
 }% 
 {% failed
   \PackageError{animals}% 
   {Unknown language specification `\CurrentOption'}% 
   {You need to supply either a known dialect label 
    or a valid language tag}% 
 }% 
}
\ProcessOptions
% Default definitions
\newcommand\catname{cat}
\newcommand\dogname{dog}
\newcommand\ladybirdname{bishy-barney-bee}
\AnyTrackedLanguages
{% 
  \ForEachTrackedDialect{\this@dialect}{% 
    \TrackLangRequireDialect{animals}{\this@dialect}% 
  }% 
}
{% no tracked languages, default already set up
}
\endinput
 In the event that a user or supplementary package for some  reason wants to load a resource file for a language that hasn’t been tracked, it might be worth providing a command for this purpose: \input tracklang
\TrackLangFromEnv
% Default definitions
\def\catname{cat}
\def\dogname{dog}
\def\ladybirdname{bishy-barney-bee}
\AnyTrackedLanguages
{% 
  \ForEachTrackedDialect{\thisdialect}{% 
    \TrackLangRequireDialect{animals}{\thisdialect}% 
  }% 
}
{% no tracked languages, default already set up
}
 The loop can then be changed to: \newcommand*{\RequireAnimalsDialect}[1]{% 
  \TrackLangRequireDialect{animals}{#1}% 
}
\ForEachTrackedDialect{\this@dialect}{% 
  \RequireAnimalsDialect\this@dialect
}% 
 The animals-en-GB.ldf file contains: \TrackLangProvidesResource{english}
\def\englishanimals{% 
  \def\catname{cat}% 
  \def\dogname{dog}% 
  \def\ladybirdname{bishy-barney-bee}% 
}
\TrackLangAddToCaptions{\englishanimals}
 The animals-en-US.ldf file contains: \TrackLangProvidesResource{en-GB}
\TrackLangRequireResource{english}
\def\enGBanimals{% 
  \englishanimals
  \def\ladybirdname{ladybird}% 
}
\TrackLangAddToCaptions{\enGBanimals}
 Here’s a German version in the file animals-german.ldf: \TrackLangProvidesResource{en-US}
\TrackLangRequireResource{english}
\def\enUSanimals{% 
  \englishanimals
  \def\ladybirdname{ladybug}% 
}
\TrackLangAddToCaptions{\enUSanimals}
\TrackLangProvidesResource{german}
\def\germananimals{% 
  \def\catname{Katze}% 
  \def\dogname{Hund}% 
  \def\ladybirdname{Marienk\"afer}% 
}
\TrackLangAddToCaptions{\germananimals}
\…animals commands.
 Here’s a babel example document: \documentclass[english,german]{article}
\usepackage{animals}
\begin{document}
\englishanimals
\catname.
\dogname.
\ladybirdname.
\germananimals
\catname.
\dogname.
\ladybirdname.
\end{document}
\documentclass[american,german,british]{article}
\usepackage{babel}
\usepackage{animals}
\begin{document}
\selectlanguage{american}
\catname.
\dogname.
\ladybirdname.
\selectlanguage{german}
\catname.
\dogname.
\ladybirdname.
\selectlanguage{british}
\catname.
\dogname.
\ladybirdname.
\end{document}
\captionsamerican hook now includes 
 Since \englishanimals
\enUSanimals
\enUSanimals includes \englishanimals, there is redundant code. However, when the british dialect is processed, this loads the file animals-en-GB.ldf but not the file animals-english.ldf (since it’s already been loaded). This means that \captionsbritish contains \enGBanimals but not  \englishanimals.
 The animals-en-US.ldf file is now: \TrackLangProvidesResource{en-GB}
\def\enGBanimals{% 
  \englishanimals
  \def\ladybirdname{ladybird}% 
}
\TrackLangRequireResourceOrDo{english}% 
{
  \TrackLangAddToCaptions{% 
    \def\ladybirdname{ladybird}% 
  }% 
}
{
  \TrackLangAddToCaptions{\enGBanimals}
}
 This means that the document that has the dialects listed in the order american, british now has \TrackLangProvidesResource{en-US}
\providecommand*{\enUSanimals}{% 
  \englishanimals
  \renewcommand*{\ladybirdname}{ladybug}% 
}
\TrackLangRequireResourceOrDo{english}
{
  \TrackLangAddToCaptions{% 
    \renewcommand*{\ladybirdname}{ladybird}% 
  }% 
}
{
  \TrackLangAddToCaptions{\enUSanimals}
}
 in the \englishanimals
\def\ladybirdname{ladybird}
\captionsbritish hook and just \enUSanimals in the \captionsamerican hook, which has removed most of the redundancy.\captionsenglish hook but not \captionsamerican or \captionsbritish, so this code doesn’t allow for switching between variants of the same language with polyglossia.5.1.2. regions.sty
\IfTrackedLanguageFileExists where if, for example, the dialect is british, the file search (v1.4+) will be: 
 
You may have wondered why mypackage-GB.ldf is included in the search given that some countries have multiple official languages, which means that the country code on its own may not indicate the language.\TrackLangRequireDialect has an optional argument for adjusting the way the resource files are loaded. Suppose I have regions-.ldf resource files, then 
 loads the resource file for the dialect given by \TrackLangRequireDialect{regions}{\this@dialect}
\this@dialect using: 
 I can use the optional argument to also load the resource file for the root language as well: \TrackLangRequireResource{\CurrentTrackedTag}
% custom file loader for regions.sty
 Now the dialect british can load both regions-GB.ldf and regions-english.ldf.\newcommand*{\RequireRegionsDialect}[1]{% 
 \TrackLangRequireDialect
   [\TrackLangRequireResource{\CurrentTrackedTag}% 
    \TrackLangRequireResource{\CurrentTrackedLanguage}% 
   ]% 
   {regions}{#1}% 
}
% Example package regions.sty
 There are separate ldf files for region and language. First are the regions.\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{regions}
\RequirePackage{tracklang}[2016/10/07]% v1.3+
\DeclareOption*{\TrackLanguageTag{\CurrentOption}}
\ProcessOptions
\newcommand*{\weightunit}{kg}
\newcommand*{\lengthunit}{mm}
\newcommand*{\currencyunit}{EUR}
\newcommand*{\unitname}{units}
\newcommand*{\RequireRegionsDialect}[1]{% 
 \TrackLangRequireDialect
  [\TrackLangRequireResource{\CurrentTrackedTag}% 
   \TrackLangRequireResource{\CurrentTrackedLanguage}% 
  ]% 
  {regions}{#1}% 
}
\AnyTrackedLanguages
{% 
 \ForEachTrackedDialect{\this@dialect}{% 
   \RequireRegionsDialect\this@dialect
 }% 
}
{% no tracked languages, default already set up
}
\endinput
 
Now the language files:\TrackLangProvidesResource{BE}
\providecommand*{\BEunits}{% 
  \renewcommand*{\weightunit}{kg}% 
  \renewcommand*{\lengthunit}{mm}% 
  \renewcommand*{\currencyunit}{EUR}% 
}
\TrackLangAddToCaptions{\BEunits}
\TrackLangProvidesResource{CA}
\providecommand*{\CAunits}{% 
  \renewcommand*{\weightunit}{kg}% 
  \renewcommand*{\lengthunit}{mm}% 
  \renewcommand*{\currencyunit}{CAD}% 
}
\TrackLangAddToCaptions{\CAunits}
\TrackLangProvidesResource{GB}
\providecommand*{\GBunits}{% 
  \renewcommand*{\weightunit}{kg}% 
  \renewcommand*{\lengthunit}{mm}% 
  \renewcommand*{\currencyunit}{GBP}% 
}
\TrackLangAddToCaptions{\GBunits}
\TrackLangProvidesResource{US}
\providecommand*{\USunits}{% 
  \renewcommand*{\weightunit}{lb}% 
  \renewcommand*{\lengthunit}{in}% 
  \renewcommand*{\currencyunit}{USD}% 
}
\TrackLangAddToCaptions{\USunits}
 
\TrackLangProvidesResource{dutch}
\providecommand*{\dutchnames}{% 
  \renewcommand*{\unitname}{meeteenheden}% 
}
\TrackLangAddToCaptions{\dutchnames}
\TrackLangProvidesResource{english}
\providecommand*{\englishnames}{% 
  \renewcommand*{\unitname}{units}% 
}
\TrackLangAddToCaptions{\englishnames}
\TrackLangProvidesResource{french}
\providecommand*{\frenchnames}{% 
  \renewcommand*{\unitname}{unit\'es}% 
}
\TrackLangAddToCaptions{\frenchnames}
\TrackLangProvidesResource{french}
\providecommand*{\germannames}{% 
  \renewcommand*{\unitname}{Ma\ss einheiten}% 
}
\TrackLangAddToCaptions{\germannames}
\documentclass[canadien]{article}
\usepackage{regions}
\begin{document}
\unitname: \weightunit, \lengthunit, \currencyunit.
\end{document}
 After this, the language file regions-french.ldf is then loaded: \TrackLangRequireResource{\CurrentTrackedTag}
\TrackLangRequireResource{\CurrentTrackedLanguage}
% Modified example package regions.sty
  Note that we still have a problem for dialect labels that are identical to root language labels with an associated territory (such as manx). This case can be checked with the following adjustment: \NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{regions}
% Pass all options to tracklang.sty:
\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{tracklang}}
\ProcessOptions
\RequirePackage{tracklang}
\newcommand*{\weightunit}{kg}
\newcommand*{\lengthunit}{mm}
\newcommand*{\currencyunit}{EUR}
\newcommand*{\unitname}{units}
\newcommand*{\defaultunits}{% 
  \renewcommand*{\weightunit}{kg}% 
  \renewcommand*{\lengthunit}{mm}% 
  \renewcommand*{\currencyunit}{EUR}% 
}
\newcommand*{\RequireRegionsDialect}[1]{% 
  \TrackLangRequireDialect
   [\TrackLangRequireResource{\CurrentTrackedTag}% 
     \ifx\CurrentTrackedTag\CurrentTrackedLanguage
       \TrackLangAddToCaptions{\defaultunits}% 
     \else
       \TrackLangRequireResource{\CurrentTrackedLanguage}% 
     \fi
   ]% 
   {regions}{#1}% 
}
\AnyTrackedLanguages
{% 
  \ForEachTrackedDialect{\this@dialect}% 
    \RequireRegionsDialect\this@dialect
  % 
}
{% no tracked languages, default already set up
}
\endinput
 In the case where both the dialect and root language label are manx with the resource files regions-manx.ldf and regions-IM.ldf, then \newcommand*{\RequireRegionsDialect}[1]{% 
  \TrackLangRequireDialect
  [\TrackLangRequireResource{\CurrentTrackedTag}% 
   \ifx\CurrentTrackedTag\CurrentTrackedLanguage
     \ifx\CurrentTrackedRegion\empty
       \TrackLangAddToCaptions{\defaultunits}% 
     \else
       \TrackLangRequireResource{\CurrentTrackedRegion}% 
     \fi
   \else
     \TrackLangRequireResource{\CurrentTrackedLanguage}% 
   \fi
  ]% 
  {regions}{#1}% 
}
\CurrentTrackedTag will be manx (the dialect label) so regions-manx.ldf will be loaded with: 
 In this case \TrackLangRequireResource{\CurrentTrackedTag}
\CurrentTrackedRegion is IM (that is, it’s not empty) so then regions-IM.ldf will be loaded with: \TrackLangRequireResource{\CurrentTrackedRegion}
\captions hook for either the dialect label or the root language label, so mappings need to be defined from the tracklang dialect label to the matching babel dialect label.
 This produces: \documentclass{article}
\usepackage{tracklang}
\TrackLanguageTag{de-US-1996}
\SetTrackedDialectLabelMap{\TrackLangLastTrackedDialect}{ngerman}
\TrackLanguageTag{en-MT}
\SetTrackedDialectLabelMap{\TrackLangLastTrackedDialect}{UKenglish}
\usepackage[main=ngerman,UKenglish]{babel}
\usepackage{regions}
\begin{document}
\selectlanguage{ngerman}
\unitname: \weightunit, \lengthunit, \currencyunit.
\selectlanguage{UKenglish}
\unitname: \weightunit, \lengthunit, \currencyunit.
\end{document}
 which produces: \documentclass{article}
\usepackage[main=ngerman,UKenglish]{babel}
\usepackage{regions}
\begin{document}
\selectlanguage{ngerman}
\unitname: \weightunit, \lengthunit, \currencyunit.
\selectlanguage{UKenglish}
\unitname: \weightunit, \lengthunit, \currencyunit.
\end{document}
 No mapping is required for the en-MT locale as it can pick up \documentclass{article}
\usepackage{tracklang}
\TrackLanguageTag{de-US-1996}
\SetTrackedDialectLabelMap{\TrackLangLastTrackedDialect}{ngerman}
\TrackLanguageTag{en-MT}
\usepackage[main=ngerman,english]{babel}
\usepackage{regions}
\begin{document}
\selectlanguage{ngerman}
\unitname: \weightunit, \lengthunit, \currencyunit.
\selectlanguage{english}
\unitname: \weightunit, \lengthunit, \currencyunit.
\end{document}
\captionsenglish when \TrackLangAddToHook (used by \TrackLangAddToCaptions) queries the root language label after failing to find the language hook from the dialect label.6. Adding Support for Language Tracking
 or (LaTeX only) \input tracklang
\RequirePackage{tracklang}
\RequirePackage over \input but you want to make  tracklang.sty skip the check for known language packages then (as from v1.3.8) define the pre-language package check hook as follows: 
 This will still pick up languages supplied through the document class options.\providecommand\@tracklang@prelangpkgcheck@hook{\endinput}
\RequirePackage{tracklang}[2019/10/06]% v1.3.8+
\input, there’s a test at the start of tracklang.tex to determine if it’s already been loaded, so you don’t need to worry if the document has already input it.
 
\TrackLangScriptMap command for each unknown script and identify this new file with \TrackLangAddExtraScriptFile (see §6.3). This usually won’t be necessary unless you have a custom script or a child script (a script that’s a sub-category of another script).\TrackLangNewLanguage (see §6.5).\TrackLangProvidePredefinedDialect.\TrackLangRegionMap command for each new region and identify this new file with \TrackLangAddExtraRegionFile (see §6.4). This usually won’t be necessary as tracklang should recognise all countries that have an alpha-2 region code, but you may require it if you need a broader region, such as EU.\TrackPredefinedDialect?\TrackLangProvidePredefinedLanguage for root languages and \TrackLangProvidePredefinedDialect for dialects with additional information, such as a region, sub-language or script (see §6.6).\TrackPredefinedDialect for recognised dialect labels or use the \AddTracked set of commands). See §6.1.\selectlanguage), add \SetCurrentTrackedDialect{} to allow the document author to easily query the current localisation settings (such as the region). See §6.2. 
6.1. Initialising a New Language or Dialect
 provided the dialect label is recognised by tracklang (all those listed in Tables 1.1, 1.2 & 1.3).\TrackPredefinedDialect{}
\TrackLocale or \TrackLanguageTag  (described in §3)  with the appropriate ISO codes if you’re not providing caption hooks.\captions, then if  doesn’t match the corresponding tracklang dialect label, you can provide a mapping using \SetTrackedDialectLabelMap, described below.6.2. Switching Language or Dialect
\SetTrackedDialectLabelMap, described below, or the language label (in which case the last dialect to be tracked with that root language will be assumed).
 
(Without this automated use of\CurrentTrackedDialect The dialect label recognised by tracklang (which may not be the same as ).\CurrentTrackedLanguage The root language label used by tracklang.\CurrentTrackedDialectModifier The dialect modifier.\CurrentTrackedDialectVariant The dialect variant.\CurrentTrackedDialectScript The dialect script. Note that if tracklang-scripts is also loaded, this allows the script direction to be accessed using 
 See §4 for further details.\TrackLangScriptAlphaToDir{\CurrentTrackedDialectScript}
\CurrentTrackedDialectSubLang The dialect sub-language code.\GetTrackedDialectAdditional The dialect’s additional information.\CurrentTrackedIsoCode The dialect’s root language  ISO code. (The first found in the sequence 639-1, 639-2, 639-3.)\CurrentTrackedRegion The dialect’s ISO 3166-1 region  code.\CurrentTrackedLanguageTag The dialect’s language tag.\SetCurrentTrackedDialect, the same information can be picked up using commands like \GetTrackedDialectScript, but that’s less convenient, especially if \languagename needs to be converted to . See the accompanying sample file sample-setlang.tex for an example.)6.3. Defining New Scripts
 The first argument  is the four-letter ISO 15924 code (such as Latn), the second argument is the numeric code (such as 215), the third argument  is the name of the script (such as Latin), the fourth argument is the direction (such as LR for left-to-right) and the final argument is the parent script (leave blank if there’s no parent). Note that this command will override any previous mapping for those codes. No check is performed to determine if they have already been defined.\TrackLangScriptMap{}{}{}{}{}
\TrackLangAddExtraScriptFile{}
6.4. Defining New Regions
 where the first argument is the numeric region code (such as 826), the second argument is the alpha-2 region code (such as \TrackLangRegionMap{}{}{}
GB) and the third argument is the alpha-3 region code (such as GBR). Note that this command will override any previous mapping for those codes. No check is performed to determine if they have already been defined.\TrackLangAddExtraRegionFile{}
6.5. Defining a New Language
 Note that \AddTrackedDialect{}{}
\AddTrackedDialect defines: 
 to the dialect label, which makes it easier to reference the last dialect to be tracked.6.6. Defining New tracklang Labels
\TrackPredefinedDialect. In the case of a dialect label that only requires the information provided in \TrackLangNewLanguage you can use: \TrackLangNewLanguage. This allows 
 to not only track the root language but also the associated ISO codes.\TrackPredefinedDialect{}
 where  is the label for the dialect’s root language (Table 1.2) and  matches the captions hook. If the dialect is already in the tracked dialect list, it won’t be added again. If the root language is already in the tracked language list, it won’t be added again. As from version 1.3 this additionally defines \AddTrackedDialect{dialect}{root language label}
\TrackLangLastTrackedDialect to  for convenient reference if required. Note that \AddTrackedDialect is internally used by commands like \TrackPredefinedDialect, \TrackLocale and \TrackLanguageTag.\captionsngerman can’t be accessed through: 
 in the resource files. In this case, a mapping may be defined between the tracklang dialect label and the closest matching label used by the language hooks. This is done through 
 where  is the tracklang label and  is the language hook label. For example: \csname captions\CurrentTrackedDialect\endcsname
 Since \TrackLanguageTag{de-AR-1996}
\SetTrackedDialectLabelMap{\TrackLangLastTrackedDialect}{ngerman}
\TrackLanguageTag internally uses \AddTrackedDialect the dialect label created by tracklang can be accessed using \TrackLangLastTrackedDialect. This means that \TrackLangAddToCaptions can now find the \captionsngerman hook even though the tracklang dialect label isn’t ngerman.\AddTrackedDialect{oldgerman}{german}
\AddTrackedLanguageIsoCodes{german}
\SetTrackedDialectModifier{oldgerman}{old}
\SetTrackedDialectModifier, since it’s assumed that any package that specifically sets the modifier in this way is using a sensible labelling system. If the modifier is obtained through commands like \TrackLocale, then the modifier is sanitized as the value may have been obtained from the operating system and there’s no guarantee that it won’t contain problematic characters.[
 whereas the variant is typically obtained by parsing the language tag._][.][@]
\AddTrackedDialect{serbianlatin}{serbian}
\AddTrackedLanguageIsoCodes{serbian}
\SetTrackedDialectModifier{serbianlatin}{latin}
\SetTrackedDialectScript{serbianlatin}{Latn}
\AddTrackedDialect{serbiancyrl}{serbian}
\AddTrackedLanguageIsoCodes{serbian}
\SetTrackedDialectScript{serbiancyrl}{Cyrl}
\AddTrackedDialect{german1901}{german}
\SetTrackedDialectVariant{german1901}{1901}
\AddTrackedDialect{mandarin}{chinese}
\AddTrackedLanguageIsoCodes{chinese}
\SetTrackedDialectSubLang{mandarin}{cmn}
\AddTrackedIsoLanguage{639-3}{cmn}{mandarin}
6.7. Example (alien.sty)
 The caption commands and language set up are in the files alien-.ldf as in the examples from §5.1. This allows for the user having already loaded tracklang before alien and used \ProvidesPackage{alien}
\inputtracklang% v1.3
\DeclareOption{martian}{% 
 \TrackPredefinedDialect{martian}
}
\DeclareOption{lowermartian}{% 
 \AddTrackedDialect{lowermartian}{martian}
 \AddTrackedLanguageIsoCodes{martian}
 \AddTrackedIsoLanguage{3166-1}{YY}{lowermartian}
 % other attributes such as
 % \SetTrackedDialectVariant{lowermartian}{...}
}
\DeclareOption{uppermartian}{% 
 \AddTrackedDialect{uppermartian}{martian}
 \AddTrackedLanguageIsoCodes{martian}
 \AddTrackedIsoLanguage{3166-1}{XX}{uppermartian}
 % other attributes such as
 % \SetTrackedDialectVariant{uppermartian}{...}
}
\ProcessOptions
\newcommand*{\selectlanguage}[1]{% 
 \def\languagename{#1}% 
 % other stuff
 \SetCurrentTrackedDialect{#1}%  
}
\AnyTrackedLanguages
{
 \ForEachTrackedDialect{\thisdialect}
 {% 
  \TrackLangRequireDialect{alien}{\thisdialect}
 }
}
\TrackLangFromEnv to pick up the locale from the operating system’s environment variables. (For example, they may have LANG set to xx.)_YY\TrackLangProvidesResource{xx-YY}
\TrackLangRequireResource{martian}% load common elements
\newcommand{\captionslowermartian}{% 
 \captionsmartian
 \def\contentsname{X'flurp}% regional variation
}
\SetTrackedDialectLabelMap{\CurrentTrackedDialect}{lowermartian}
\TrackLangFromEnv before using the alien package.
 The rest is as before.\ProvidesPackage{alien}
\input{tracklang}% needs v1.3
\TrackLangIfKnownLang{martian}
{}% tracklang already knows about the martian language
{
 % tracklang doesn't known about the martian language, so define it
 % with ISO 639-1 (xx) and ISO 639-2 (xxx) codes:
 \TrackLangNewLanguage{martian}{xx}{xxx}{}{}{}{Latn}
}
A. Region and Script Mappings
 
Alpha-2 
Alpha-3 
Numeric 
Alpha-2 
Alpha-3 
Numeric 
 
AD 
AND 
020
 AE 
ARE 
784 
 
AF 
AFG 
004
 AG 
ATG 
028 
 
AI 
AIA 
660
 AL 
ALB 
008 
 
AM 
ARM 
051
 AO 
AGO 
024 
 
AQ 
ATA 
010
 AR 
ARG 
032 
 
AS 
ASM 
016
 AT 
AUT 
040 
 
AU 
AUS 
036
 AW 
ABW 
533 
 
AX 
ALA 
248
 AZ 
AZE 
031 
 
BA 
BIH 
070
 BB 
BRB 
052 
 
BD 
BGD 
050
 BE 
BEL 
056 
 
BF 
BFA 
854
 BG 
BGR 
100 
 
BH 
BHR 
048
 BI 
BDI 
108 
 
BJ 
BEN 
204
 BL 
BLM 
652 
 
BM 
BMU 
060
 BN 
BRN 
096 
 
BO 
BOL 
068
 BQ 
BES 
535 
 
BR 
BRA 
076
 BS 
BHS 
044 
 
BT 
BTN 
064
 BV 
BVT 
074 
 
BW 
BWA 
072
 BY 
BLR 
112 
 
BZ 
BLZ 
084
 CA 
CAN 
124 
 
CC 
CCK 
166
 CD 
COD 
180 
 
CF 
CAF 
140
 CG 
COG 
178 
 
CH 
CHE 
756
 CI 
CIV 
384 
 
CK 
COK 
184
 CL 
CHL 
152 
 
CM 
CMR 
120
 CN 
CHN 
156 
 
CO 
COL 
170
 CR 
CRI 
188 
 
CU 
CUB 
192
 CV 
CPV 
132 
 
CW 
CUW 
531
 CX 
CXR 
162 
 
CY 
CYP 
196
 CZ 
CZE 
203 
 
DE 
DEU 
276
 DJ 
DJI 
262 
 
DK 
DNK 
208
 DM 
DMA 
212 
 
DO 
DOM 
214
 DZ 
DZA 
012 
 
EC 
ECU 
218
 EE 
EST 
233 
 
EG 
EGY 
818
 EH 
ESH 
732 
 
ER 
ERI 
232
 ES 
ESP 
724 
 
ET 
ETH 
231
 FI 
FIN 
246 
 
FJ 
FJI 
242
 FK 
FLK 
238 
 
FM 
FSM 
583
 FO 
FRO 
234 
 
FR 
FRA 
250
 GA 
GAB 
266 
 
GB 
GBR 
826
 GD 
GRD 
308 
 
GE 
GEO 
268
 GF 
GUF 
254 
 
GG 
GGY 
831
 GH 
GHA 
288 
 
GI 
GIB 
292
 GL 
GRL 
304 
 
GM 
GMB 
270
 GN 
GIN 
324 
 
GP 
GLP 
312
 GQ 
GNQ 
226 
 
GR 
GRC 
300
 GS 
SGS 
239 
 
GT 
GTM 
320
 GU 
GUM 
316 
 
GW 
GNB 
624
 GY 
GUY 
328 
 
HK 
HKG 
344
 HM 
HMD 
334 
 
HN 
HND 
340
 HR 
HRV 
191 
 
HT 
HTI 
332
 HU 
HUN 
348 
 
ID 
IDN 
360
 IE 
IRL 
372 
 
IL 
ISR 
376
 IM 
IMN 
833 
 
IN 
IND 
356
 IO 
IOT 
086 
 
IQ 
IRQ 
368
 IR 
IRN 
364 
 
IS 
ISL 
352
 IT 
ITA 
380 
 
JE 
JEY 
832
 JM 
JAM 
388 
 
JO 
JOR 
400
 JP 
JPN 
392 
 
KE 
KEN 
404
 KG 
KGZ 
417 
 
KH 
KHM 
116
 KI 
KIR 
296 
 
KM 
COM 
174
 KN 
KNA 
659 
 
KP 
PRK 
408
 KR 
KOR 
410 
 
KW 
KWT 
414
 KY 
CYM 
136 
 
KZ 
KAZ 
398
 LA 
LAO 
418 
 
LB 
LBN 
422
 LC 
LCA 
662 
 
LI 
LIE 
438
 LK 
LKA 
144 
 
LR 
LBR 
430
 LS 
LSO 
426 
 
LT 
LTU 
440
 LU 
LUX 
442 
 
LV 
LVA 
428
 LY 
LBY 
434 
 
MA 
MAR 
504
 MC 
MCO 
492 
 
MD 
MDA 
498
 ME 
MNE 
499 
 
MF 
MAF 
663
 MG 
MDG 
450 
 
MH 
MHL 
584
 MK 
MKD 
807 
 
ML 
MLI 
466
 MM 
MMR 
104 
 
MN 
MNG 
496
 MO 
MAC 
446 
 
MP 
MNP 
580
 MQ 
MTQ 
474 
 
MR 
MRT 
478
 MS 
MSR 
500 
 
MT 
MLT 
470
 MU 
MUS 
480 
 
MV 
MDV 
462
 MW 
MWI 
454 
 
MX 
MEX 
484
 MY 
MYS 
458 
 
MZ 
MOZ 
508
 NA 
NAM 
516 
 
NC 
NCL 
540
 NE 
NER 
562 
 
NF 
NFK 
574
 NG 
NGA 
566 
 
NI 
NIC 
558
 NL 
NLD 
528 
 
NO 
NOR 
578
 NP 
NPL 
524 
 
NR 
NRU 
520
 NU 
NIU 
570 
 
NZ 
NZL 
554
 OM 
OMN 
512 
 
PA 
PAN 
591
 PE 
PER 
604 
 
PF 
PYF 
258
 PG 
PNG 
598 
 
PH 
PHL 
608
 PK 
PAK 
586 
 
PL 
POL 
616
 PM 
SPM 
666 
 
PN 
PCN 
612
 PR 
PRI 
630 
 
PS 
PSE 
275
 PT 
PRT 
620 
 
PW 
PLW 
585
 PY 
PRY 
600 
 
QA 
QAT 
634
 RE 
REU 
638 
 
RO 
ROU 
642
 RS 
SRB 
688 
 
RU 
RUS 
643
 RW 
RWA 
646 
 
SA 
SAU 
682
 SB 
SLB 
090 
 
SC 
SYC 
690
 SD 
SDN 
729 
 
SE 
SWE 
752
 SG 
SGP 
702 
 
SH 
SHN 
654
 SI 
SVN 
705 
 
SJ 
SJM 
744
 SK 
SVK 
703 
 
SL 
SLE 
694
 SM 
SMR 
674 
 
SN 
SEN 
686
 SO 
SOM 
706 
 
SR 
SUR 
740
 SS 
SSD 
728 
 
ST 
STP 
678
 SV 
SLV 
222 
 
SX 
SXM 
534
 SY 
SYR 
760 
 
SZ 
SWZ 
748
 TC 
TCA 
796 
 
TD 
TCD 
148
 TF 
ATF 
260 
 
TG 
TGO 
768
 TH 
THA 
764 
 
TJ 
TJK 
762
 TK 
TKL 
772 
 
TL 
TLS 
626
 TM 
TKM 
795 
 
TN 
TUN 
788
 TO 
TON 
776 
 
TR 
TUR 
792
 TT 
TTO 
780 
 
TV 
TUV 
798
 TW 
TWN 
158 
 
TZ 
TZA 
834
 UA 
UKR 
804 
 
UG 
UGA 
800
 UM 
UMI 
581 
 
US 
USA 
840
 UY 
URY 
858 
 
UZ 
UZB 
860
 VA 
VAT 
336 
 
VC 
VCT 
670
 VE 
VEN 
862 
 
VG 
VGB 
092
 VI 
VIR 
850 
 
VN 
VNM 
704
 VU 
VUT 
548 
 
WF 
WLF 
876
 WS 
WSM 
882 
 
YE 
YEM 
887
 YT 
MYT 
175 
 
ZA 
ZAF 
710
 ZM 
ZMB 
894 
 ZW 
ZWE 
716 
 
Alpha-2 
Numeric 
Direction 
Description 
 
Adlm 
166 
RL 
Adlam. 
 
Afak 
439 
varies 
Afaka. 
 
Aghb 
239 
LR 
Caucasian Albanian. 
 
Ahom 
338 
LR 
Ahom, Tai Ahom. 
 
Arab 
160 
RL 
Arabic. 
 
Aran 
161 
RL 
Arabic (Nastaliq variant). 
 
Armi 
124 
RL 
Imperial Aramaic. 
 
Armn 
230 
LR 
Armenian. 
 
Avst 
134 
RL 
Avestan. 
 
Bali 
360 
LR 
Balinese. 
 
Bamu 
435 
LR 
Bamum. 
 
Bass 
259 
LR 
Bassa Vah. 
 
Batk 
365 
LR 
Batak. 
 
Beng 
334 
LR 
Bhaiksuki. 
 
Blis 
550 
varies 
Blissymbols. 
 
Bopo 
285 
LR 
Bopomofo. 
 
Brah 
300 
LR 
Brahmi. 
 
Brai 
570 
LR 
Braille. 
 
Bugi 
367 
LR 
Buginese. 
 
Buhd 
372 
LR 
Buhid. 
 
Cakm 
349 
LR 
Chakma. 
 
Cans 
440 
LR 
Unified Canadian Aboriginal Syllabics. 
 
Cari 
201 
LR 
Carian. 
 
Cham 
358 
LR 
Cham. 
 
Cher 
445 
LR 
Cherokee. 
 
Cirt 
291 
varies 
Cirth. 
 
Copt 
204 
LR 
Coptic. 
 
Cprt 
403 
RL 
Cypriot. 
 
Cyrl 
220 
LR 
Cyrillic. 
 
Cyrs 
221 
varies 
Cyrillic (Old Church Slavonic variant). 
 
Deva 
315 
LR 
Devanagari (Nagari). 
 
Dsrt 
250 
LR 
Deseret (Mormon). 
 
Dupl 
755 
LR 
Duployan shorthand, Duployan stenography. 
 
Egyd 
070 
RL 
Egyptian demotic. 
 
Egyh 
060 
RL 
Egyptian hieratic. 
 
Egyp 
050 
LR 
Egyptian hieroglyphs. 
 
Elba 
226 
LR 
Elbasan. 
 
Ethi 
430 
LR 
Ethiopic (Ge’ez). 
 
Geok 
241 
LR 
Khutsuri (Asomtavruli and Nuskhuri). 
 
Geor 
240 
LR 
Georgian (Mkhedruli). 
 
Glag 
225 
LR 
Glagolitic. 
 
Goth 
206 
LR 
Gothic. 
 
Gran 
343 
LR 
Grantha. 
 
Grek 
200 
LR 
Greek. 
 
Gujr 
320 
LR 
Gujarati. 
 
Guru 
310 
LR 
Gurmukhi. 
 
Hanb 
503 
LR 
Han with Bopomofo (alias for Han + Bopomofo). 
 
Hang 
286 
LR 
Hangul. 
 
Hani 
500 
LR 
Han (Hanzi, Kanji, Hanja). 
 
Hano 
371 
LR 
Hanunoo. 
 
Hans 
501 
varies 
Han (Simplified variant). 
 
Hant 
502 
varies 
Han (Traditional variant). 
 
Hatr 
127 
RL 
Hatran. 
 
Hebr 
125 
RL 
Hebrew. 
 
Hira 
410 
LR 
Hiragana. 
 
Hluw 
080 
LR 
Anatolian Hieroglyphs (Luwian Hieroglyphs, Hittite Hieroglyphs). 
 
Hmng 
450 
LR 
Pahawh Hmong. 
 
Hrkt 
412 
varies 
Japanese syllabaries (alias for Hiragana + Katakana). 
 
Hung 
176 
RL 
Old Hungarian (Hungarian Runic). 
 
Inds 
610 
RL 
Indus (Harappan). 
 
Ital 
210 
LR 
Old Italic (Etruscan, Oscan, etc.) 
 
Jamo 
284 
LR 
Jamo (alias for Jamo subset of Hangul). 
 
Java 
361 
LR 
Javanese. 
 
Jpan 
413 
varies 
Japanese (alias for Han + Hiragana + Katakana). 
 
Jurc 
510 
LR 
Jurchen. 
 
Kali 
357 
LR 
Kayah Li. 
 
Kana 
411 
LR 
Katakana. 
 
Khar 
305 
RL 
Kharoshthi. 
 
Khmr 
355 
LR 
Khmer. 
 
Khoj 
322 
LR 
Khojki. 
 
Kitl 
505 
LR 
Khitan large script. 
 
Kits 
288 
TB 
Khitan small script. 
 
Knda 
345 
LR 
Kannada. 
 
Kore 
287 
LR 
Korean (alias for Hangul + Han). 
 
Kpel 
436 
LR 
Kpelle. 
 
Kthi 
317 
LR 
Kaithi. 
 
Lana 
351 
LR 
Tai Tham (Lanna). 
 
Laoo 
356 
LR 
Lao. 
 
Latf 
217 
varies 
Latin (Fraktur variant). 
 
Latg 
216 
LR 
Latin (Gaelic variant). 
 
Latn 
215 
LR 
Latin. 
 
Leke 
364 
LR 
Leke. 
 
Lepc 
335 
LR 
Lepcha. 
 
Limb 
336 
LR 
Limbu. 
 
Lina 
400 
LR 
Linear A. 
 
Linb 
401 
LR 
Linear B. 
 
Lisu 
399 
LR 
Lisu (Fraser). 
 
Loma 
437 
LR 
Loma. 
 
Lyci 
202 
LR 
Lycian. 
 
Lydi 
116 
RL 
Lydian. 
 
Mahj 
314 
LR 
Mahajani. 
 
Mand 
140 
RL 
Mandaic, Mandaean. 
 
Mani 
139 
RL 
Manichaean. 
 
Marc 
332 
LR 
Marchen. 
 
Maya 
090 
varies 
Mayan hieroglyphs. 
 
Mend 
438 
RL 
Mende Kikakui. 
 
Merc 
101 
RL 
Meroitic Cursive. 
 
Mero 
100 
RL 
Meroitic Hieroglyphs. 
 
Mlym 
347 
LR 
Malayalam. 
 
Modi 
324 
LR 
Modi. 
 
Mong 
145 
TB 
Mongolian. 
 
Moon 
218 
varies 
Moon (Moon code, Moon script, Moon type). 
 
Mroo 
199 
LR 
Mro, Mru. 
 
Mtei 
337 
LR 
Meitei Mayek (Meithei, Meetei). 
 
Mult 
323 
LR 
Multani. 
 
Mymr 
350 
LR 
Myanmar (Burmese). 
 
Narb 
106 
RL 
Old North Arabian (Ancient North Arabian). 
 
Nbat 
159 
RL 
Nabataean. 
 
Newa 
333 
LR 
Newa, Newar, Newari. 
 
Nkgb 
420 
LR 
Nakhi Geba. 
 
Nkoo 
165 
RL 
N’Ko. 
 
Nshu 
499 
LR 
Nushu. 
 
Ogam 
212 
varies 
Ogham. 
 
Olck 
261 
LR 
Ol Chiki. 
 
Orkh 
175 
RL 
Old Turkic, Orkhon Runic. 
 
Orya 
327 
LR 
Oriya. 
 
Osge 
219 
LR 
Osage. 
 
Osma 
260 
LR 
Osmanya. 
 
Palm 
126 
RL 
Palmyrene. 
 
Pauc 
263 
LR 
Pau Cin Hau. 
 
Perm 
227 
LR 
Old Permic. 
 
Phag 
331 
TB 
Phags-pa. 
 
Phli 
131 
RL 
Inscriptional Pahlavi. 
 
Phlp 
132 
RL 
Psalter Pahlavi. 
 
Phlv 
133 
RL 
Book Pahlavi. 
 
Phnx 
115 
RL 
Phoenician. 
 
Piqd 
293 
LR 
Klingon (KLI plqaD). 
 
Plrd 
282 
LR 
Miao (Pollard). 
 
Prti 
130 
RL 
Inscriptional Parthian. 
 
Qaaa 
900 
varies 
Reserved for private use (start). 
 
Qaai 
908 
varies 
Private use. 
 
Qabx 
949 
varies 
Reserved for private use (end). 
 
Rjng 
363 
LR 
Rejang (Redjang, Kaganga). 
 
Roro 
620 
varies 
Rongorongo. 
 
Runr 
211 
LR 
Runic. 
 
Samr 
123 
RL 
Samaritan. 
 
Sara 
292 
varies 
Sarati. 
 
Sarb 
105 
RL 
Old South Arabian. 
 
Saur 
344 
LR 
Saurashtra. 
 
Sgnw 
095 
TB 
SignWriting. 
 
Shaw 
281 
LR 
Shavian (Shaw). 
 
Shrd 
319 
LR 
Sharada. 
 
Sidd 
302 
LR 
Siddham. 
 
Sind 
318 
LR 
Khudawadi, Sindhi. 
 
Sinh 
348 
LR 
Sinhala. 
 
Sora 
398 
LR 
Sora Sompeng. 
 
Sund 
362 
LR 
Sundanese. 
 
Sylo 
316 
LR 
Syloti Nagri. 
 
Syrc 
135 
RL 
Syriac. 
 
Syre 
138 
RL 
Syriac (Estrangelo variant). 
 
Syrj 
137 
RL 
Syriac (Western variant). 
 
Syrn 
136 
RL 
Syriac (Eastern variant). 
 
Tagb 
373 
LR 
Tagbanwa. 
 
Takr 
321 
LR 
Takri. 
 
Tale 
353 
LR 
Tai Le. 
 
Talu 
354 
LR 
New Tai Lue. 
 
Taml 
346 
LR 
Tamil. 
 
Tang 
520 
LR 
Tangut. 
 
Tavt 
359 
LR 
Tai Viet. 
 
Telu 
340 
LR 
Telugu. 
 
Teng 
290 
LR 
Tengwar. 
 
Tfng 
120 
LR 
Tifinagh (Berber). 
 
Tglg 
370 
LR 
Tagalog (Baybayin, Alibata). 
 
Thaa 
170 
RL 
Thaana. 
 
Thai 
352 
LR 
Thai. 
 
Tibt 
330 
LR 
Tibetan. 
 
Tirh 
326 
LR 
Tirhuta. 
 
Ugar 
040 
LR 
Ugaritic. 
 
Vaii 
470 
LR 
Vai. 
 
Visp 
280 
LR 
Visible Speech. 
 
Wara 
262 
LR 
Warang Citi (Varang Kshiti). 
 
Wole 
480 
RL 
Woleai. 
 
Xpeo 
030 
LR 
Old Persian. 
 
Xsux 
020 
LR 
Cuneiform, Sumero-Akkadian. 
 
Yiii 
460 
LR 
Yi. 
 
Zinh 
994 
inherited 
Inherited script. 
 
Zmth 
995 
LR 
Mathematical notation. 
 
Zsye 
993 
varies 
Symbols (emoji variant). 
 
Zsym 
996 
varies 
Symbols. 
 
Zxxx 
997 
varies 
Unwritten documents. 
 
Zyyy 
998 
varies 
Undetermined script. 
 Zzzz 
999 
varies 
Uncoded script. Symbols
Glossary
Command Summary
@
A
\TrackLangLastTrackedDialect to provide a convenient way to reference the last dialect to be tracked. §6.5; 76\AddTrackedDialect{}{}\TrackLangNewLanguage. §6.6; 78C
\SetCurrentTrackedDialect to the dialect label, which may be the supplied  label or the mapped label or, if  is a root language label, the last tracked dialect for the given root language. §5; 46\SetCurrentTrackedDialect to the additional part associated with the dialect (may be empty). §5; 46\SetCurrentTrackedDialect to the associated modifier (may be empty). §5; 46\SetCurrentTrackedDialect to the script associated with the dialect, or to the default script for the language. §5; 47\SetCurrentTrackedDialect to the sub language associated with the dialect (may be empty). §5; 46\SetCurrentTrackedDialect to the associated variant (may be empty). §5; 46\SetCurrentTrackedDialect to the ISO 639-1 or 639-2 or 639-3 language code (may be empty). §5; 46\SetCurrentTrackedDialect to the associated root language label. §5; 46\SetCurrentTrackedDialect to the language tag that identifies the dialect or und if no match. §5; 47\SetCurrentTrackedDialect to the ISO 3166-1 region code associated with the dialect (may be empty). §5; 46F
G
I
\SetCurrentTrackedDialect{}\CurrentTrackedTag is set to  and  is done, otherwise  is done. §5; 45S
\captions. §6.6; 78T
\GetTrackedDialectFromLanguageTag to the closest match. §5; 36\TrackLanguageTag but does  if the tag doesn’t contain a valid language code. If successful, does  after tracking the language. §3; 21\TrackLangAddToHook{}{captions}\TrackPredefinedDialect.\inputencodingname if it has been defined or utf8 otherwise. §5; 53LC_ALL before using \TrackLangParseFromEnv to skip the environment variable query. §3; 25\TrackLangParseFromEnv to the code-set. §3; 26\TrackLangParseFromEnv to the language code. §3; 26\TrackLangParseFromEnv to the modifier. §3; 26\TrackLangParseFromEnv to the territory. §3; 26\TrackLangEnv not already set, parses \TrackLangEnv if it has been set, and adds the dialect if it’s recognised. §3; 23\TrackLangEnv. §3; 27\TrackPredefinedDialect. §6.6; 77\TrackPredefinedDialect. §6.6; 77\ProvidesFile. §5; 52LC_ALL environment variable via the shell escape or, with LuaTeX, \directlua. §3; 26LC_ALL environment variable and then by the  environment variable via the shell escape or, with LuaTeX, \directlua. §3; 26\TrackLangAddToHook but redefines the hook rather than appending to it. §5; 55\TrackLangRequireResource but does  if the file doesn’t exist. §5; 54\TrackLangRequireDialect. §5; 45\TrackLangRequireResource but does  if the file is now loaded or  if the file has already been loaded. §5; 53\TrackLangScriptMap to the associated alpha code . §4; 32\ifTrackLangShowWarnings to false. §3; 24\ifTrackLangShowWarnings to true. §3; 24\TrackLangEnv. §3; 20Index
Symbols
\\ (escaped backslash)25$ (environment variable)25@
@ (catcode 11)19\@nil37A
\AtBeginDocument37B
C
D
E
LC_MONETARY26F
G
H
I
\inputencodingname53\InputIfFileExistsJ
K
L
M
N
O
P
Q
R
S
T
\trans@languages35U
V
W
X
\xpg@loaded35Y
Z
1Thass Broad Norfolk, my bewties :-P