diff options
| author | Maurizio M. Gavioli <mmg@vistamaresoft.com> | 2024-06-05 10:32:23 +0200 |
|---|---|---|
| committer | Maurizio M. Gavioli <mmg@vistamaresoft.com> | 2024-06-19 10:10:26 +0200 |
| commit | 53755824fb5ec7014d0e256fad124d3d805fd1ca (patch) | |
| tree | 5b49dadb510e7ce4f34d2008852a91fafddd06fe /core/text/i18n | |
| parent | 7064166da255b4f6c6828b6f4eb5322f966a39c4 (diff) | |
Separate the I18N calls for immutable strings and for pluraliseable strings.
Also update tests.
Diffstat (limited to 'core/text/i18n')
| -rw-r--r-- | core/text/i18n/doc.odin | 52 | ||||
| -rw-r--r-- | core/text/i18n/i18n.odin | 138 |
2 files changed, 144 insertions, 46 deletions
diff --git a/core/text/i18n/doc.odin b/core/text/i18n/doc.odin index 54bf8b80f..56ce9bde5 100644 --- a/core/text/i18n/doc.odin +++ b/core/text/i18n/doc.odin @@ -1,31 +1,44 @@ /* -The `i18n` package is flexible and easy to use. +The `i18n` package is a flexible and easy to use way to localise applications. -It has one call to get a translation: `get`, which the user can alias into something like `T`. +It has two calls to get a translation: `get()` amd `get_n()`, which the user can alias into something like `T` and `Tn` +with statements like: + T :: i18n.get + Tn :: i18n.get_n. -`get`, referred to as `T` here, has a few different signatures. -All of them will return the key if the entry can't be found in the active translation catalog. +`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 semtece is fixed and it will have only one possible translation in any other language. -- `T(key)` returns the translation of `key`. -- `T(key, n)` returns a pluralized translation of `key` according to value `n`. +`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 which be used to select the correct form according to the pluraliser attached to the message catalogue when initially loaded; +for instance, to summarise a rather complex matter, some languages use the singular form when reerring 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 an a universal plural form: +for istance, Chinese has just one form for any quantity, while Welsh may have up to 6 different forms for specific different quantities. -- `T(section, key)` returns the translation of `key` in `section`. -- `T(section, key, n)` returns a pluralized translation of `key` in `section` according to value `n`. +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 speciic catalogue is supplied -By default lookup take place in the global `i18n.ACTIVE` catalog for ease of use. -If you want to override which translation to use, for example in a language preview dialog, you can use the following: +- `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. -- `T(key, n, catalog)` returns the pluralized version of `key` from explictly supplied catalog. -- `T(section, key, n, catalog)` returns the pluralized version of `key` in `section` from explictly supplied catalog. +- `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 (or not passing n) returns the singular form. -Passing n != 1 returns plural form 1. +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 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 value and returning which plural slot should be used. +This is a procedure that maps an integer to an integer, taking a numbe of item and returning which plural slot should be used. You can also assign it to a loaded catalog after parsing, of course. @@ -35,6 +48,7 @@ Example: import "core:text/i18n" T :: i18n.get + Tn :: i18n.get_n mo :: proc() { using fmt @@ -60,9 +74,9 @@ Example: println(T("Hellope, World!")) println("-----") // We pass 1 into `T` to get the singular format string, then 1 again into printf. - printf(T("There is %d leaf.\n", 1), 1) + 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(T("There is %d leaf.\n", 42), 42) + printf(Tn("There is %d leaf.\n", 42), 42) /* This isn't in the translation catalog, so the key is passed back untranslated. @@ -99,8 +113,8 @@ Example: println("-----") println("--- apple_count section ---") println("apple_count:%d apple(s) =") - println("\t 1 =", T("apple_count", "%d apple(s)", 1)) - println("\t 42 =", T("apple_count", "%d apple(s)", 42)) + println("\t 1 =", Tn("apple_count", "%d apple(s)", 1)) + println("\t 42 =", Tn("apple_count", "%d apple(s)", 42)) } */ package i18n diff --git a/core/text/i18n/i18n.odin b/core/text/i18n/i18n.odin index 64593c4e8..87bd77045 100644 --- a/core/text/i18n/i18n.odin +++ b/core/text/i18n/i18n.odin @@ -84,64 +84,149 @@ DEFAULT_PARSE_OPTIONS :: Parse_Options{ merge_sections = false, } +// ***************** +// get() PROC GROUP +// ***************** + /* - Several ways to use: - - get(key), which defaults to the singular form and i18n.ACTIVE catalog, or - - get(key, number), which returns the appropriate plural from the active catalog, or - - get(key, number, catalog) to grab text from a specific one. + Returns the first translation string for the passed `key`. + It is also aliases 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 :: proc(key: string, number := 1, catalog: ^Translation = ACTIVE) -> (value: string) { +get_single_section :: proc(key: string, catalog: ^Translation = ACTIVE) -> (value: string) { + return get_by_slot(key, 0, catalog) +} + +/* + 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 (sometime also called 'context') from which to lookup 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 :: proc(section, key: string, catalog: ^Translation = ACTIVE) -> (value: string) { + return get_by_slot(section, key, 0, catalog) +} + +get :: proc{get_single_section, get_by_section} + +// ***************** +// get_n() PROC GROUP +// ***************** + +/* + Returns the translation string for the passed `key` in a specific plural form (if present in the catalogue). + It is also aliases 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. + - 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_single_section_w_plural :: proc(key: string, quantity: int, catalog: ^Translation = ACTIVE) -> (value: string) { /* A lot of languages use singular for 1 item and plural for 0 or more than 1 items. This is our default pluralize rule. */ - plural := 1 if number != 1 else 0 + slot := 1 if quantity != 1 else 0 if catalog.pluralize != nil { - plural = catalog.pluralize(number) + slot = catalog.pluralize(quantity) } - return get_by_slot(key, plural, catalog) + return get_by_slot(key, slot, catalog) } /* - Several ways to use: - - get(section, key), which defaults to the singular form and i18n.ACTIVE catalog, or - - get(section, key, number), which returns the appropriate plural from the active catalog, or - - get(section, key, number, catalog) to grab text from a specific one. + 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_section :: proc(section, key: string, number := 1, catalog: ^Translation = ACTIVE) -> (value: string) { +get_by_section_w_plural :: proc(section, key: string, quantity: int, catalog: ^Translation = ACTIVE) -> (value: string) { /* A lot of languages use singular for 1 item and plural for 0 or more than 1 items. This is our default pluralize rule. */ - plural := 1 if number != 1 else 0 + slot := 1 if quantity != 1 else 0 if catalog.pluralize != nil { - plural = catalog.pluralize(number) + slot = catalog.pluralize(quantity) } - return get_by_slot(section, key, plural, catalog) + return get_by_slot(section, key, slot, catalog) } -get :: proc{get_single_section, get_by_section} +get_n :: proc{get_single_section_w_plural, get_by_section_w_plural} + +// ***************** +// get_by_slot() PROC GROUP +// ***************** /* - Several ways to use: - - get_by_slot(key), which defaults to the singular form and i18n.ACTIVE catalog, or - - 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. + 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. + - qantity: 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 :: proc(key: string, slot := 0, catalog: ^Translation = ACTIVE) -> (value: string) { +get_by_slot_single_section :: proc(key: string, slot: int, catalog: ^Translation = ACTIVE) -> (value: string) { return get_by_slot_by_section("", key, slot, catalog) } /* - Several ways to use: - - get_by_slot(key), which defaults to the singular form and i18n.ACTIVE catalog, or + 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. + - qantity: 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_by_section :: proc(section, key: string, slot := 0, catalog: ^Translation = ACTIVE) -> (value: string) { +get_by_slot_by_section :: proc(section, key: string, slot: int, catalog: ^Translation = ACTIVE) -> (value: string) { if catalog == nil || section not_in catalog.k_v { /* Return the key if the catalog catalog hasn't been initialized yet, or the section is not present. @@ -161,7 +246,6 @@ get_by_slot_by_section :: proc(section, key: string, slot := 0, catalog: ^Transl get_by_slot :: proc{get_by_slot_single_section, get_by_slot_by_section} /* - Same for destroy: - destroy(), to clean up the currently active catalog catalog i18n.ACTIVE - destroy(catalog), to clean up a specific catalog. */ @@ -181,4 +265,4 @@ destroy :: proc(catalog: ^Translation = ACTIVE, allocator := context.allocator) delete(catalog.k_v) strings.intern_destroy(&catalog.intern) free(catalog) -}
\ No newline at end of file +} |