package core:text/i18n
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))
}
Index
Types (4)
Constants (2)
Variables (2)
Procedure Groups (5)
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_mo_file
- parse_mo_from_bytes
- parse_qt_linguist_file
- parse_qt_linguist_from_bytes
- read_u16
- read_u32
- parse_mo (procedure groups)
- parse_qt (procedure groups)
Parse_Options ¶
Parse_Options :: struct { merge_sections: bool, }
Related Procedures With Parameters
- parse_mo_file
- parse_mo_from_bytes
- parse_qt_linguist_file
- parse_qt_linguist_from_bytes
- parse_mo (procedure groups)
- parse_qt (procedure groups)
Related Constants
Section ¶
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
- destroy
- get_by_section
- get_by_section_with_quantity
- get_by_slot_by_section
- get_by_slot_single_section
- get_single_section
- get_single_section_with_quantity
- get (procedure groups)
- get_by_slot (procedure groups)
- get_n (procedure groups)
Related Procedures With Returns
- parse_mo_file
- parse_mo_from_bytes
- parse_qt_linguist_file
- parse_qt_linguist_from_bytes
- parse_mo (procedure groups)
- parse_qt (procedure groups)
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
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_u32 ¶
Helpers.
Procedure Groups
get ¶
get :: proc{ get_single_section, get_by_section, }
get_by_slot ¶
get_by_slot :: proc{ get_by_slot_single_section, get_by_slot_by_section, }
get_n ¶
get_n :: proc{ get_single_section_with_quantity, get_by_section_with_quantity, }
parse_mo ¶
parse_mo :: proc{ parse_mo_file, parse_mo_from_bytes, }
parse_qt ¶
parse_qt :: proc{ parse_qt_linguist_file, parse_qt_linguist_from_bytes, }
Source Files
Generation Information
Generated with odin version dev-2024-12 (vendor "odin") Windows_amd64 @ 2024-12-17 21:11:02.071075100 +0000 UTC