Additional Localization (Units: A Unit Conversion Program and Scientific Calculator)

### 16.2 Additional Localization ¶

Sometimes the locale isn’t sufficient to determine unit preferences. There could be regional preferences, or a company could have specific preferences. Though probably uncommon, such differences could arise with the choice of English customary units outside of English-speaking countries. To address this, `units` allows specifying definitions that depend on environment variable settings. The environment variables can be controlled based on the current locale, or the user can set them to force a particular group of definitions.

A conditional block of definitions in a units data file begins with either ‘`!var`’ or ‘`!varnot`’ following by an environment variable name and then a space separated list of values. The leading ‘`!`’ must appear in the first column of a units data file, and the conditional block is terminated by ‘`!endvar`’. Definitions in blocks beginning with ‘`!var`’ are executed only if the environment variable is exactly equal to one of the listed values. Definitions in blocks beginning with ‘`!varnot`’ are executed only if the environment variable does not equal any of the list values.

The inch has long been a customary measure of length in many places. The word comes from the Latin uncia meaning “one twelfth,” referring to its relationship with the foot. By the 20th century, the inch was officially defined in English-speaking countries relative to the yard, but until 1959, the yard differed slightly among those countries. In France the customary inch, which was displaced in 1799 by the meter, had a different length based on a french foot. These customary definitions could be accommodated as follows:

    !var INCH_UNIT usa
    yard          3600|3937 m
    !endvar

    !var INCH_UNIT canada
    yard          0.9144 meter
    !endvar

    !var INCH_UNIT uk
    yard          0.91439841 meter
    !endvar

    !var INCH_UNIT canada uk usa
    foot          1|3 yard
    inch          1|12 foot
    !endvar

    !var INCH_UNIT france
    foot          144|443.296 m
    inch          1|12 foot
    line          1|12 inch
    !endvar

    !varnot INCH_UNIT usa uk france canada
    !message Unknown value for INCH_UNIT
    !endvar

When `units` reads the above definitions it will check the environment variable `INCH_UNIT` and load only the definitions for the appropriate section. If `INCH_UNIT` is unset or is not set to one of the four values listed, then `units` will run the last block. In this case that block uses the ‘`!message`’ command to display a warning message. Alternatively that block could set default values.

In order to create default values that are overridden by user settings the data file can use the ‘`!set`’ command, which sets an environment variable only if it is not already set; these settings are only for the current `units` invocation and do not persist. So if the example above were preceded by ‘`!set INCH_UNIT france`’, then this would make ‘`france`’ the default value for `INCH_UNIT`. If the user had set the variable in the environment before invoking `units`, then `units` would use the user’s value.

To link these settings to the user’s locale you combine the ‘`!set`’ command with the ‘`!locale`’ command. If you wanted to combine the above example with suitable locales you could do by preceding the above definition with the following:

    !locale en_US
    !set INCH_UNIT usa
    !endlocale
    !locale en_GB
    !set INCH_UNIT uk
    !endlocale
    !locale en_CA
    !set INCH_UNIT canada
    !endlocale
    !locale fr_FR
    !set INCH_UNIT france
    !endlocale
    !set INCH_UNIT france

These definitions set the overall default for `INCH_UNIT` to ‘`france`’ and set default values for four locales appropriately. The overall default setting comes last so that it only applies when `INCH_UNIT` was not set by one of the other commands or by the user.

If the variable given after ‘`!var`’ or ‘`!varnot`’ is undefined, then `units` prints an error message and ignores the definitions that follow. Use ‘`!set`’ to create defaults to prevent this situation from arising. The `-c` option only checks the definitions that are active for the current environment and locale, so when adding new definitions take care to check that all cases give rise to a well defined set of definitions.