[← Home](../README.md) · [Libraries](README.md)
# locale.library — Internationalisation
## Overview
`locale.library` (OS 2.1+) provides the Amiga's internationalisation (i18n) framework: language-aware string lookup via catalogues, locale-sensitive date/number/currency formatting, and character classification. Applications that use locale.library display in the user's preferred language automatically.
```mermaid
flowchart TD
APP["Application"] -->|"GetCatalogStr(cat, ID, fallback)"| LOC["locale.library"]
LOC -->|"Looks up string ID"| CAT["myapp.catalog
(LOCALE:Catalogs/deutsch/)"]
CAT -->|"Found"| DE["'Datei öffnen'"]
LOC -->|"Not found"| FB["Fallback:
'Open File'"]
style LOC fill:#e8f4fd,stroke:#2196f3,color:#333
style CAT fill:#c8e6c9,stroke:#2e7d32,color:#333
```
---
## Catalogue System
### Creating String IDs
```c
/* Typically in a generated header (from CatComp or FlexCat): */
#define MSG_OPEN_FILE 1
#define MSG_SAVE_FILE 2
#define MSG_QUIT 3
#define MSG_ERROR_NOTFOUND 100
/* Built-in English strings (fallback): */
static const char *builtinStrings[] = {
[MSG_OPEN_FILE] = "Open File",
[MSG_SAVE_FILE] = "Save File",
[MSG_QUIT] = "Quit",
[MSG_ERROR_NOTFOUND] = "File not found",
};
```
### Using Catalogues
```c
struct Library *LocaleBase = OpenLibrary("locale.library", 38);
/* Open the application's catalogue: */
struct Catalog *cat = OpenCatalog(NULL, "myapp.catalog",
OC_BuiltInLanguage, (ULONG)"english",
TAG_DONE);
/* NULL for first arg = use current locale */
/* Get localised string (with English fallback): */
STRPTR openStr = GetCatalogStr(cat, MSG_OPEN_FILE, "Open File");
/* Returns German "Datei öffnen" if German catalogue exists,
otherwise the fallback "Open File" */
/* Use throughout the application: */
Printf("%s\n", GetCatalogStr(cat, MSG_QUIT, "Quit"));
/* Cleanup: */
CloseCatalog(cat);
CloseLibrary(LocaleBase);
```
### Catalogue File Structure
```
LOCALE:Catalogs/deutsch/myapp.catalog ← German
LOCALE:Catalogs/français/myapp.catalog ← French
LOCALE:Catalogs/italiano/myapp.catalog ← Italian
```
Catalogues are compiled from `.cd` (catalogue description) and `.ct` (catalogue translation) files using **CatComp** or **FlexCat**:
```
; myapp.cd — catalogue description
MSG_OPEN_FILE (1//)
Open File
;
MSG_SAVE_FILE (2//)
Save File
;
```
```
; myapp_deutsch.ct — German translation
MSG_OPEN_FILE
Datei öffnen
;
MSG_SAVE_FILE
Datei speichern
;
```
---
## Locale-Aware Formatting
```c
struct Locale *loc = OpenLocale(NULL); /* user's default locale */
Printf("Country: %s\n", loc->loc_CountryName);
Printf("Language: %s\n", loc->loc_PrefLanguages[0]);
Printf("Decimal: '%s'\n", loc->loc_DecimalPoint); /* "." or "," */
Printf("Grouping: '%s'\n", loc->loc_GroupSeparator); /* "," or "." */
Printf("Currency: '%s'\n", loc->loc_MonCS); /* "$", "€", "£" */
```
### Date Formatting
```c
/* Format a date stamp according to locale: */
struct DateStamp ds;
DateStamp(&ds);
/* FormatDate uses a hook to receive characters: */
char dateBuf[64];
int pos = 0;
/* Simple hook that fills a buffer: */
void __saveds __asm DateHookFunc(
register __a0 struct Hook *hook,
register __a1 char ch)
{
char *buf = hook->h_Data;
buf[pos++] = ch;
buf[pos] = 0;
}
struct Hook dateHook;
dateHook.h_Entry = (HOOKFUNC)DateHookFunc;
dateHook.h_Data = dateBuf;
FormatDate(loc, "%A, %e %B %Y", &ds, &dateHook);
/* Result (German locale): "Mittwoch, 23 April 2025" */
/* Result (US locale): "Wednesday, 23 April 2025" */
```
### Format Codes
| Code | Output | Example |
|---|---|---|
| `%A` | Full weekday name | "Wednesday" / "Mittwoch" |
| `%a` | Abbreviated weekday | "Wed" / "Mi" |
| `%B` | Full month name | "April" |
| `%b` | Abbreviated month | "Apr" |
| `%d` | Day (01–31) | "23" |
| `%e` | Day (1–31, no leading zero) | "23" |
| `%H` | Hour (00–23) | "14" |
| `%I` | Hour (01–12) | "02" |
| `%M` | Minute (00–59) | "30" |
| `%S` | Second (00–59) | "00" |
| `%p` | AM/PM | "PM" |
| `%Y` | 4-digit year | "2025" |
| `%y` | 2-digit year | "25" |
---
## Character Classification
```c
/* Locale-aware character checks: */
if (IsAlpha(loc, ch)) /* alphabetic (language-aware) */
if (IsUpper(loc, ch)) /* uppercase */
if (IsLower(loc, ch)) /* lowercase */
if (IsDigit(loc, ch)) /* digit */
if (IsAlNum(loc, ch)) /* alphanumeric */
if (IsPunct(loc, ch)) /* punctuation */
if (IsSpace(loc, ch)) /* whitespace */
/* Locale-aware case conversion: */
char upper = ConvToUpper(loc, ch);
char lower = ConvToLower(loc, ch);
/* Locale-aware string comparison: */
LONG result = StrnCmp(loc, str1, str2, -1, SC_COLLATE2);
/* SC_ASCII = byte comparison */
/* SC_COLLATE1 = primary collation (ignores accents) */
/* SC_COLLATE2 = full collation */
```
---
## References
- NDK39: `libraries/locale.h`
- ADCD 2.1: locale.library autodocs
- CatComp / FlexCat documentation for catalogue compilation