Aros/Developer/Docs/Libraries/Locale

Navbar for the Aros wikibook
Aros User
Aros User Docs
Aros User FAQs
Aros User Applications
Aros User DOS Shell
Aros/User/AmigaLegacy
Aros Dev Docs
Aros Developer Docs
Porting Software from AmigaOS/SDL
For Zune Beginners
Zune .MUI Classes
For SDL Beginners
Aros Developer BuildSystem
Specific platforms
Aros x86 Complete System HCL
Aros x86 Audio/Video Support
Aros x86 Network Support
Aros Intel AMD x86 Installing
Aros Storage Support IDE SATA etc
Aros Poseidon USB Support
x86-64 Support
Motorola 68k Amiga Support
Linux and FreeBSD Support
Windows Mingw and MacOSX Support
Android Support
Arm Raspberry Pi Support
PPC Power Architecture
misc
Aros Public License

Introduction

edit

here is a global environment variable (Language) that holds the current active language.

You can check this yourself by typing "getenv language" (without the quotes) into a shell. Or it can be used in a script as variable $Language.

It can also be done programming using the OpenLocale() function (with NULL as parameter to return the current locale information in struct Locale)

System

edit

The locale.library provides us tools to localize applications. Localized strings are stored in separate languages catalogs files, under Catalogs directories. AROS Development Environment macros can build the required files. This document gives you a work-flow to localize applications or localize existing applications or create catalogs files for existing localized applications.

For each language supported, the system has a LOCALE:Languages/ file:

LOCALE:Languages/klingon.language

System translations are in LOCALE:Catalogs/ language directories:

LOCALE:Catalogs/klingon/

Each application needs its proper Catalogs directory:

my_app/Catalogs/

Translation files are in languages directories:

my_app/Catalogs/klingon/my_app.catalog

Appplications

edit

Each application supporting localization has its own catalogs directory:

AROS/Contrib/my_app/catalogs

Strings are initially stored in a catalog description file:

AROS/Contrib/my_app/catalogs/my_app.cd
This file is structured as:
;
MSG_TITLE (//)
My Application
;
MSG_MY_MESSAGE (//)
My application message
;
...

Translations are stored in catalog translation files:

AROS/Contrib/my_app/catalogs/klingon.ct

Structured as:

## version $VER: my_app.catalog 1.0 (23.05.2004)
## language klingon
## codeset 0
;
MSG_TITLE
tlhIngan maH
;
MSG_MY_MESSAGE
Sujatlh 'e' yImev
;
...

The catalogs build file

Localization is provided by:

AROS/Contrib/my_app/locale.c
AROS/contrib/my_app/locale.h

Application: _(MSG_MY_TITLE)

As STRPTR.

Or with: __(MSG_MY_MESSAGE)

As IPTR (1) The application source file

In AROS/Contrib/my_app/my_app.c, initialize locale with:

...

#include "locale.h"

main()
{

...

Use the strings names from the .cd file. For instance, on a Zune application: MUIA_Application_Title, __(MSG_TITLE), ... } The application build file

Add the locale file target to the FILE section of AROS/Contrib/my_app/mmakefile.src:
FILES    := my_app \
               ...
               locale

Add the pre-requisite target for locale:
#MM- my_app: \
  ...
#MM my_app-catalogs
Build the locale
AROS/

To build the application and locale files:
make my_app

To update the translation (.ct) files:
make my_app-catalogsWarning:	If you are updating the description (.cd) files, build my_app target to update its strings file.

Build System

edit

AROS Metamake builds required files with its build file present as:

AROS/Contrib/my_app/catalogs/mmakefile.src
# Copyright © 2004, The AROS Development Team. All rights reserved.
# $Id: mmakefile.src,v 1.2 2004/02/19 22:05:38 john doe Exp $

include $(TOP)/config/make.cfg

%build_catalogs mmake=my_app-catalogs \
  name=My_App \
  subdir= \
  dir=$(AROSDIR)/Extras/My_App/Catalogs
Application directory
AROS/Contrib/my_app/

FlexCat

edit

FlexCat is a tool to create Amiga localization catalogs, as well as source and header files, out of catalog descriptions.

The version in AROS/tools is 2.4, with a developers.readme saying to treat it as freeware with source code, but not to fork it. The history file tells us that version 2.4 is from 28 November 1999. Not all websites referred to in the documentation still exist, but flexcat indeed supports the 2.4 version, with no mention of further development. Is a port a fork? If not, does a former port become a fork e.g. just because AROS becomes 68k? What if there originally was only one port, but someone else does another one - who is the forker? Maybe the author was just too imprecise and should have provided a definition of fork...

1 The AROS project stamps are for 7 March 2009, so there may well have been changes for the AROS version over the last decade.

2 The last release on Aminet is version 2.7 on 29 June 2010, by the project, which claims a copyright starting in 2002.

The original homepage is outdated. It's now a GPL licensed product which is maintained here. Of course the 2.7 distribution does not contain the source code, because the project is Open Source and the source code is available for everybody. The release archives contain binaries only for all supported platforms.

  • Update the sources in AROS from a stable release of FlexCat
  • Make it buildable again, perhaps my merging in commits from prior commits.
  • C_h_orig.sd is no longer available in current FlexCat. Find a replacement which works with the AROS build-system.
  • Bring back all fixes for AROS to the current trunk of FlexCat. Either bei joining the project on Sourceforge or sending it to the maintainer.

We would appreciate if you would join the team and commit the changes to the SVN repository on sourceforge.net. Just ask Jens Langer (damato#light-speed.de) to add you the list of developers.

Optionally: wait till the "vendor" branch is available in AROS repository and work with that.

Examples

edit
/*
    Copyright © 1995-2004, The AROS Development Team. All rights reserved.
    $Id: locale.c 30794 2009-03-08 02:19:07Z neil $
*/

#include <exec/types.h>
#include <proto/locale.h>

#define CATCOMP_ARRAY
#include "strings.h"

#define CATALOG_NAME     "AiRcOS.catalog"
#define CATALOG_VERSION  0

/*** Variables **************************************************************/
struct Catalog *catalog;

/*** Functions **************************************************************/
/* Main *********************************************************************/
CONST_STRPTR _(ULONG id)
{
    if (LocaleBase != NULL && catalog != NULL)
    {
	return GetCatalogStr(catalog, id, CatCompArray[id].cca_Str);
    } 
    else 
    {
	return CatCompArray[id].cca_Str;
    }
}

/* Setup ********************************************************************/
VOID Locale_Initialize(VOID)
{
    if (LocaleBase != NULL)
    {
        catalog = OpenCatalog
        ( 
            NULL, CATALOG_NAME, OC_Version, CATALOG_VERSION, TAG_DONE 
        );
    }
    else
    {
        catalog = NULL;
    }
}

VOID Locale_Deinitialize(VOID)
{
    if(LocaleBase != NULL && catalog != NULL) CloseCatalog(catalog);
}
#ifndef _LOCALE_H_
#define _LOCALE_H_

/*
    Copyright © 2003-2004, The AROS Development Team. All rights reserved.
    $Id: locale.h 30794 2009-03-08 02:19:07Z neil $
*/

#include <exec/types.h>

#define CATCOMP_NUMBERS
#include "strings.h"

/*** Prototypes *************************************************************/
/* Main *********************************************************************/
CONST_STRPTR _(ULONG ID);       /* Get a message, as a STRPTR */
#define __(id) ((IPTR) _(id))   /* Get a message, as an IPTR */

/* Setup ********************************************************************/
VOID Locale_Initialize(VOID);
VOID Locale_Deinitialize(VOID);

#endif /* _LOCALE_H_ */

References

edit
/* constants for GetLocaleStr() */
#define DAY_1		1	/* Sunday    */
#define DAY_2		2	/* Monday    */
#define DAY_3		3	/* Tuesday   */
#define DAY_4		4	/* Wednesday */
#define DAY_5		5	/* Thursday  */
#define DAY_6		6	/* Friday    */
#define DAY_7		7	/* Saturday  */

#define ABDAY_1	8	/* Sun */
#define ABDAY_2	9	/* Mon */
#define ABDAY_3	10	/* Tue */
#define ABDAY_4	11	/* Wed */
#define ABDAY_5	12	/* Thu */
#define ABDAY_6	13	/* Fri */
#define ABDAY_7	14	/* Sat */

#define MON_1		15	/* January   */
#define MON_2		16	/* February  */
#define MON_3		17	/* March     */
#define MON_4		18	/* April     */
#define MON_5		19	/* May	     */
#define MON_6		20	/* June      */
#define MON_7		21	/* July      */
#define MON_8		22	/* August    */
#define MON_9		23	/* September */
#define MON_10		24	/* October   */
#define MON_11		25	/* November  */
#define MON_12		26	/* December  */

#define ABMON_1	27	/* Jan */
#define ABMON_2	28	/* Feb */
#define ABMON_3	29	/* Mar */
#define ABMON_4	30	/* Apr */
#define ABMON_5	31	/* May */
#define ABMON_6	32	/* Jun */
#define ABMON_7	33	/* Jul */
#define ABMON_8	34	/* Aug */
#define ABMON_9	35	/* Sep */
#define ABMON_10	36	/* Oct */
#define ABMON_11	37	/* Nov */
#define ABMON_12	38	/* Dec */

#define YESSTR		39	/* affirmative response for yes/no queries */
#define NOSTR		40	/* negative response for yes/no queries    */

#define AM_STR		41	/* AM */
#define PM_STR		42	/* PM */

#define SOFTHYPHEN	43	/* soft hyphenation */
#define HARDHYPHEN	44	/* hard hyphenation */

#define OPENQUOTE	45	/* start of quoted block */
#define CLOSEQUOTE	46	/* end of quoted block	 */

#define YESTERDAYSTR	47	/* Yesterday */
#define TODAYSTR	48	/* Today     */
#define TOMORROWSTR	49	/* Tomorrow  */
#define FUTURESTR	50	/* Future    */

#define MAXSTRMSG	51	/* current number of defined strings */

/* This structure must only be allocated by locale.library and is READ-ONLY! */

struct Locale
{
    STRPTR  loc_LocaleName;	      /* locale's name		     */
    STRPTR  loc_LanguageName;	      /* language of this locale     */
    STRPTR  loc_PrefLanguages[10];    /* preferred languages	     */
    ULONG   loc_Flags;		      /* always 0 for now	     */

    ULONG   loc_CodeSet;	      /* always 0 for now	     */
    ULONG   loc_CountryCode;	      /* user's country code	     */
    ULONG   loc_TelephoneCode;	      /* country's telephone code    */
    LONG    loc_GMTOffset;	      /* minutes from GMT	     */
    UBYTE   loc_MeasuringSystem;      /* what measuring system?      */
    UBYTE   loc_CalendarType;	      /* what calendar type?	     */
    UBYTE   loc_Reserved0[2];

    STRPTR  loc_DateTimeFormat;       /* regular date & time format  */
    STRPTR  loc_DateFormat;	      /* date format by itself	     */
    STRPTR  loc_TimeFormat;	      /* time format by itself	     */

    STRPTR  loc_ShortDateTimeFormat;  /* short date & time format    */
    STRPTR  loc_ShortDateFormat;      /* short date format by itself */
    STRPTR  loc_ShortTimeFormat;      /* short time format by itself */

    /* for numeric values */
    STRPTR  loc_DecimalPoint;	      /* character before the decimals */
    STRPTR  loc_GroupSeparator;       /* separates groups of digits    */
    STRPTR  loc_FracGroupSeparator;   /* separates groups of digits    */
    UBYTE  *loc_Grouping;	      /* size of each group	       */
    UBYTE  *loc_FracGrouping;	      /* size of each group	       */

    /* for monetary values */
    STRPTR  loc_MonDecimalPoint;
    STRPTR  loc_MonGroupSeparator;
    STRPTR  loc_MonFracGroupSeparator;
    UBYTE  *loc_MonGrouping;
    UBYTE  *loc_MonFracGrouping;
    UBYTE   loc_MonFracDigits;	      /* digits after the decimal point   */
    UBYTE   loc_MonIntFracDigits;     /* for international representation */
    UBYTE   loc_Reserved1[2];

    /* for currency symbols */
    STRPTR  loc_MonCS;		      /* currency symbol	      */
    STRPTR  loc_MonSmallCS;	      /* symbol for small amounts     */
    STRPTR  loc_MonIntCS;	      /* international (ISO 4217) code */

    /* for positive monetary values */
    STRPTR  loc_MonPositiveSign;      /* indicate positive money value	 */
    UBYTE   loc_MonPositiveSpaceSep;  /* determine if separated by space */
    UBYTE   loc_MonPositiveSignPos;   /* position of positive sign	 */
    UBYTE   loc_MonPositiveCSPos;     /* position of currency symbol	 */
    UBYTE   loc_Reserved2;

    /* for negative monetary values */
    STRPTR  loc_MonNegativeSign;      /* indicate negative money value	 */
    UBYTE   loc_MonNegativeSpaceSep;  /* determine if separated by space */
    UBYTE   loc_MonNegativeSignPos;   /* position of negative sign	 */
    UBYTE   loc_MonNegativeCSPos;     /* position of currency symbol	 */
    UBYTE   loc_Reserved3;
};

/* constants for Locale.loc_MeasuringSystem */
#define MS_ISO		0	/* international metric system */
#define MS_AMERICAN	1	/* american system	       */
#define MS_IMPERIAL	2	/* imperial system	       */
#define MS_BRITISH	3	/* british system	       */

/* constants for Locale.loc_CalendarType */
#define CT_7SUN 0   /* 7 days a week, Sunday is the first day	 */
#define CT_7MON 1   /* 7 days a week, Monday is the first day	 */
#define CT_7TUE 2   /* 7 days a week, Tuesday is the first day	 */
#define CT_7WED 3   /* 7 days a week, Wednesday is the first day */
#define CT_7THU 4   /* 7 days a week, Thursday is the first day  */
#define CT_7FRI 5   /* 7 days a week, Friday is the first day	 */
#define CT_7SAT 6   /* 7 days a week, Saturday is the first day  */

/* constants for Locale.loc_MonPositiveSpaceSep and Locale.loc_MonNegativeSpaceSep */
#define SS_NOSPACE 0  /* cur. symbol is NOT separated from value with a space */
#define SS_SPACE   1  /* cur. symbol IS separated from value with a space     */

/* constants for Locale.loc_MonPositiveSignPos and Locale.loc_MonNegativeSignPos */
#define SP_PARENS    0	/* () surround the quantity and currency_symbol   */
#define SP_PREC_ALL  1	/* sign string comes before amount and symbol	  */
#define SP_SUCC_ALL  2	/* sign string comes after amount and symbol	  */
#define SP_PREC_CURR 3	/* sign string comes right before currency symbol */
#define SP_SUCC_CURR 4	/* sign string comes right after currency symbol  */

/* constants for Locale.loc_MonPositiveCSPos and Locale.loc_MonNegativeCSPos */
#define CSP_PRECEDES 0	/* currency symbol comes before value */
#define CSP_SUCCEEDS 1	/* currency symbol comes after value  */

/* elements of the byte arrays pointed to by:
 *   Locale.loc_Grouping
 *   Locale.loc_FracGrouping
 *   Locale.loc_MonGrouping
 *   Locale.loc_MonFracGrouping
 * are interpreted as follows:
 *
 *    255     indicates that no further grouping is to be performed
 *    0       indicates that the previous element is to be repeatedly used for the remainder of the digits
 *    <other> the number of digits that comprises the current group
 */

/* This structure must only be allocated by locale.library and is READ-ONLY! */

struct Catalog
{
    struct Node cat_Link;	/* for internal linkage    */
    UWORD	cat_Pad;	/* to longword align	   */
    STRPTR	cat_Language;	/* language of the catalog */
    ULONG	cat_CodeSet;	/* currently always 0	   */
    UWORD	cat_Version;	/* version of the catalog  */
    UWORD	cat_Revision;	/* revision of the catalog */
};
void CloseCatalog(struct Catalog *catalog) (A0)
void CloseLocale(struct Locale *locale) (A0)

ULONG ConvToLower(const struct Locale *locale, ULONG character) (A0, D0)
ULONG ConvToUpper(const struct Locale *locale, ULONG character) (A0, D0)

void FormatDate(const struct Locale *locale, CONST_STRPTR formatString, const struct DateStamp *date, const struct Hook *hook) (A0, A1, A2, A3)

APTR FormatString(const struct Locale *locale, CONST_STRPTR fmtTemplate, CONST_APTR dataStream, const struct Hook *putCharFunc) (A0, A1, A2, A3)

CONST_STRPTR GetCatalogStr(const struct Catalog *catalog, ULONG stringNum, CONST_STRPTR defaultString) (A0, D0, A1)
CONST_STRPTR GetLocaleStr(const struct Locale *locale, ULONG stringNum) (A0, D0)

ULONG IsAlNum(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsAlpha(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsCntrl(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsDigit(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsGraph(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsLower(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsPrint(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsPunct(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsSpace(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsUpper(const struct Locale *locale, ULONG character) (A0, D0)
ULONG IsXDigit(const struct Locale *locale, ULONG character) (A0, D0)

struct Catalog *OpenCatalogA(const struct Locale *locale, CONST_STRPTR name, const struct TagItem *tags) (A0, A1, A2)

struct Locale *OpenLocale(CONST_STRPTR name) (A0)

BOOL ParseDate(struct Locale *locale, struct DateStamp *date, CONST_STRPTR fmtTemplate, struct Hook *getCharFunc) (A0, A1, A2, A3)
struct Locale *LocalePrefsUpdate(struct Locale *locale) (A0)

ULONG StrConvert(const struct Locale *locale, CONST_STRPTR string, APTR buffer, ULONG bufferSize, ULONG type) (A0, A1, A2, D0, D1)
LONG StrnCmp(const struct Locale *locale, CONST_STRPTR string1, CONST_STRPTR string2, LONG length, ULONG type) (A0, A1, A2, D0, D1)

private
APTR LocRawDoFmt(CONST_STRPTR FormatString, APTR DataStream, VOID_FUNC PutChProc, APTR PutChData) (A0, A1, A2, A3)
LONG LocStrnicmp(CONST_STRPTR string1, CONST_STRPTR string2, LONG length) (A0, A1, D0)
LONG LocStricmp(CONST_STRPTR string1, CONST_STRPTR string2) (A0, A1)
ULONG LocToLower(ULONG character) (D0)
ULONG LocToUpper(ULONG character) (D0)
LONG LocDateToStr(struct DateTime *datetime) (D1)
LONG LocStrToDate(struct DateTime *datetime) (D1)
CONST_STRPTR LocDosGetLocalizedString(LONG stringNum) (D1)