package core:text/i18n

⌘K
Ctrl+K
or
/

    Overview

    The i18n package is a flexible and easy to use way to localise applications.

    It has two calls to get a translation: get() and get_n(), which the user can alias into something like T and Tn with statements like:

    T  :: i18n.get
    Tn :: i18n.get_n.
    
    

    get() is used for retrieving the translation of sentences which never change in form, like for instance "Connection established" or "All temporary files have been deleted". Note that the number (singular, dual, plural, whatever else) is not relevant: the sentence is fixed and it will have only one possible translation in any other language.

    get_n() is used for retrieving the translations of sentences which change according to the number of items referenced. The various signatures of get_n() have one more parameter, n, which will receive that number and be used to select the correct form according to the pluralizer attached to the message catalogue when initially loaded; for instance, to summarise a rather complex matter, some languages use the singular form when referring to 0 items and some use the (only in their case) plural forms; also, languages may have more or less quantifier forms than a single singular form and a universal plural form: for instance, Chinese has just one form for any quantity, while Welsh may have up to 6 different forms for specific different quantities.

    Both get() and get_n(), referred to as T and Tn here, have several different signatures. All of them will return the key if the entry can't be found in the active translation catalogue. By default lookup take place in the global i18n.ACTIVE catalogue for ease of use, unless a specific catalogue is supplied.

    T(key) returns the translation of key. T(key, catalog) returns the translation of key from explictly supplied catalogue. T(section, key) returns the translation of key in section. T(section, key, catalog) returns the translation of key in section from explictly supplied catalogue.

    Tn(key, n) returns the translation of key according to number of items n. Tn(key, n, catalog) returns the translation of key from explictly supplied catalogue. Tn(section, key, n) returns the translation of key in section according to number of items n. Tn(section, key, n, catalog) returns the translation of key in section according to number of items n from explictly supplied catalogue.

    If a catalog has translation contexts or sections, then omitting it in the above calls looks up in section "".

    The default pluralization rule is n != 1, which is to say that passing n == 1 returns the singular form (in slot 0). Passing n != 1 returns the plural form in slot 1 (if any).

    Should a language not conform to this rule, you can pass a pluralizer procedure to the catalog parser. This is a procedure that maps an integer to an integer, taking a quantity and returning which plural slot should be used.

    You can also assign it to a loaded catalog after parsing, of course.

    Example:
    import "core:fmt"
    import "core:text/i18n"
    
    T  :: i18n.get
    Tn :: i18n.get_n
    
    mo :: proc() {
    	using fmt
    
    	err: i18n.Error
    
    	// Parse MO file and set it as the active translation so we can omit `get`'s "catalog" parameter.
    	i18n.ACTIVE, err = i18n.parse_mo(#load("translations/nl_NL.mo"))
    	defer i18n.destroy()
    
    	if err != .None { return }
    
    	// These are in the .MO catalog.
    	println("-----")
    	println(T(""))
    	println("-----")
    	println(T("There are 69,105 leaves here."))
    	println("-----")
    	println(T("Hellope, World!"))
    	println("-----")
    	// We pass 1 into `T` to get the singular format string, then 1 again into printf.
    	printf(Tn("There is %d leaf.\n", 1), 1)
    	// We pass 42 into `T` to get the plural format string, then 42 again into printf.
    	printf(Tn("There is %d leaf.\n", 42), 42)
    
    	// This isn't in the translation catalog, so the key is passed back untranslated.
    	println("-----")
    	println(T("Come visit us on Discord!"))
    }
    
    qt :: proc() {
    	using fmt
    
    	err: i18n.Error
    
    	// Parse QT file and set it as the active translation so we can omit `get`'s "catalog" parameter.
    	i18n.ACTIVE, err = i18n.parse_qt(#load("translations/nl_NL-qt-ts.ts"))
    	defer i18n.destroy()
    
    	if err != .None { return }
    
    	// These are in the .TS catalog. As you can see they have sections.
    	println("--- Page section ---")
    	println("Page:Text for translation =", T("Page", "Text for translation"))
    	println("-----")
    	println("Page:Also text to translate =", T("Page", "Also text to translate"))
    	println("-----")
    	println("--- installscript section ---")
    	println("installscript:99 bottles of beer on the wall =", T("installscript", "99 bottles of beer on the wall"))
    	println("-----")
    	println("--- apple_count section ---")
    	println("apple_count:%d apple(s) =")
    	println("\t 1  =", Tn("apple_count", "%d apple(s)", 1))
    	println("\t 42 =", Tn("apple_count", "%d apple(s)", 42))
    }
    

    Types

    Error ¶

    Error :: enum int {
    	// General return values.
    	None                           = 0, 
    	Empty_Translation_Catalog, 
    	Duplicate_Key, 
    	// Couldn't find, open or read file.
    	File_Error, 
    	// File too short.
    	Premature_EOF, 
    	// GNU Gettext *.MO file errors.
    	MO_File_Invalid_Signature, 
    	MO_File_Unsupported_Version, 
    	MO_File_Invalid, 
    	MO_File_Incorrect_Plural_Count, 
    	// Qt Linguist *.TS file errors.
    	TS_File_Parse_Error, 
    	TS_File_Expected_Context, 
    	TS_File_Expected_Context_Name, 
    	TS_File_Expected_Source, 
    	TS_File_Expected_Translation, 
    	TS_File_Expected_NumerusForm, 
    	Bad_Str, 
    	Bad_Id, 
    }
    Related Procedures With Returns

    Parse_Options ¶

    Parse_Options :: struct {
    	merge_sections: bool,
    }
    Related Procedures With Parameters
    Related Constants

    Section ¶

    Section :: map[string][]string
     

    The main data structure. This can be generated from various different file formats, as long as we have a parser for them.

    Translation ¶

    Translation :: struct {
    	k_v:       map[string]map[string][]string,
    	// k_v[section][key][plural_form] = ...
    	intern:    strings.Intern,
    	pluralize: proc(number: int) -> int,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Constants

    DEFAULT_PARSE_OPTIONS ¶

    DEFAULT_PARSE_OPTIONS :: Parse_Options{merge_sections = false}

    MAX_PLURALS ¶

    MAX_PLURALS :: min(max(#config(ODIN_i18N_MAX_PLURAL_FORMS, 10), 1), 255)
     

    Allow between 1 and 255 plural forms. Default: 10.

    Variables

    ACTIVE ¶

    ACTIVE: ^Translation
     

    Currently active catalog.

    TS_XML_Options ¶

    TS_XML_Options: encoding_xml.Options = …

    Procedures

    destroy ¶

    destroy :: proc(catalog: ^Translation = ACTIVE, allocator := context.allocator) {…}
     

    destroy(), to clean up the currently active catalog catalog i18n.ACTIVE destroy(catalog), to clean up a specific catalog.

    get_by_section ¶

    get_by_section :: proc(section, key: string, catalog: ^Translation = ACTIVE) -> (value: string) {…}
     

    Returns the first translation string for the passed key in a specific section or context. It is also aliases with get().

    Two ways to use it: get(section, key), which defaults to the i18n.ACTIVE catalogue, or get(section, key, catalog) to grab text from a specific loaded catalogue

    Inputs:
    section: the catalogue section (sometimes also called 'context') in which to look up the translation key: the string to translate catalog: the catalogue to use for the translation (defaults to i18n.ACTIVE)

    Returns:
    the translated string, or the original key if no translation was found.

    get_by_section_with_quantity ¶

    get_by_section_with_quantity :: proc(section, key: string, quantity: int, catalog: ^Translation = ACTIVE) -> (value: string) {…}
     

    Returns the translation string for the passed key in a specific plural form (if present in the catalogue) in a specific section or context. It is also aliases with get_n().

    Two ways to use it: get(section, key, quantity), which returns the appropriate plural from the active catalogue, or get(section, key, quantity, catalog) to grab text from a specific loaded catalogue

    Inputs:
    section: the catalogue section (sometime also called 'context') from which to lookup the translation key: the string to translate qantity: the quantity of item to be used to select the correct plural form catalog: the catalogue to use for the translation (defaults to i18n.ACTIVE)

    Returns:
    the translated string, or the original key if no translation was found

    get_by_slot_by_section ¶

    get_by_slot_by_section :: proc(section, key: string, slot: int, catalog: ^Translation = ACTIVE) -> (value: string) {…}
     

    Two ways to use: get_by_slot(key, slot), which returns the requested plural from the active catalog, or get_by_slot(key, slot, catalog) to grab text from a specific one.

    If a file format parser doesn't (yet) support plural slots, each of the slots will point at the same string.

    Inputs:
    section: the catalogue section (sometime also called 'context') from which to lookup the translation key: the string to translate. slot: the translation slot to choose (slots refer to plural forms specific for each language and their meaning changes from catalogue to catalogue). catalog: the catalogue to use for the translation (defaults to i18n.ACTIVE)

    Returns:
    the translated string or the original key if no translation was found.

    get_by_slot_single_section ¶

    get_by_slot_single_section :: proc(key: string, slot: int, catalog: ^Translation = ACTIVE) -> (value: string) {…}
     

    Two ways to use: get_by_slot(key, slot), which returns the requested plural from the active catalogue, or get_by_slot(key, slot, catalog) to grab text from a specific loaded catalogue.

    If a file format parser doesn't (yet) support plural slots, each of the slots will point at the same string. section: the catalogue section (sometime also called 'context') from which to lookup the translation

    Inputs:
    key: the string to translate. slot: the translation slot to choose (slots refer to plural forms specific for each language and their meaning changes from catalogue to catalogue). catalog: the catalogue to use for the translation (defaults to i18n.ACTIVE)

    Returns:
    the translated string, or the original key if no translation was found.

    get_single_section ¶

    get_single_section :: proc(key: string, catalog: ^Translation = ACTIVE) -> (value: string) {…}
     

    Returns the first translation string for the passed key. It is also aliased with get().

    Two ways to use it: get(key), which defaults to the i18n.ACTIVE catalogue, or get(key, catalog) to grab text from a specific loaded catalogue

    Inputs:
    key: the string to translate catalog: the catalogue to use for the translation (defaults to i18n.ACTIVE)

    Returns:
    the translated string, or the original key if no translation was found.

    get_single_section_with_quantity ¶

    get_single_section_with_quantity :: proc(key: string, quantity: int, catalog: ^Translation = ACTIVE) -> (value: string) {…}
     

    Returns the translation string for the passed key in a specific plural form (if present in the catalogue). It is also aliased with get_n().

    Two ways to use it: get_n(key, quantity), which returns the appropriate plural from the active catalogue, or get_n(key, quantity, catalog) to grab text from a specific loaded catalogue

    Inputs:
    key: the string to translate quantity: the quantity of item to be used to select the correct plural form catalog: the catalogue to use for the translation (defaults to i18n.ACTIVE)

    Returns:
    the translated string, or the original key if no translation was found.

    parse_mo_file ¶

    parse_mo_file :: proc(filename: string, options: Parse_Options = DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) {…}

    parse_mo_from_bytes ¶

    parse_mo_from_bytes :: proc(data: []u8, options: Parse_Options = DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) {…}

    parse_qt_linguist_file ¶

    parse_qt_linguist_file :: proc(filename: string, options: Parse_Options = DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) {…}

    parse_qt_linguist_from_bytes ¶

    parse_qt_linguist_from_bytes :: proc(data: []u8, options: Parse_Options = DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) {…}

    read_u16 ¶

    read_u16 :: proc(data: []u8, native_endian: bool = true) -> (res: u16, err: Error) {…}

    read_u32 ¶

    read_u32 :: proc(data: []u8, native_endian: bool = true) -> (res: u32, err: Error) {…}
     

    Helpers.

    Procedure Groups

    Source Files

    Generation Information

    Generated with odin version dev-2024-12 (vendor "odin") Windows_amd64 @ 2024-12-17 21:11:02.071075100 +0000 UTC